home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / program / misc / octamed-.lha / Programmers / proplayer.a < prev    next >
Text File  |  1995-06-30  |  97KB  |  3,497 lines

  1. ;============================================================================
  2. ;    proplayer.a
  3. ;    ~~~~~~~~~~~
  4. ; $VER: proplayer 6.3 (19.06.1995)
  5. ;
  6. ; The music player routine for MMD0/MMD1/MMD2 MED/OctaMED
  7. ; four-channel modules.
  8. ;
  9. ; Copyright © 1995 Teijo Kinnunen and RBF Software.
  10. ;
  11. ; Written by Teijo Kinnunen.
  12. ; Comments/questions/bug reports can be sent to:
  13. ;    Teijo Kinnunen
  14. ;    Oksantie 19
  15. ;    FIN-86300  OULAINEN
  16. ;    FINLAND
  17. ;    email: Teijo.Kinnunen@oulu.fi
  18. ;
  19. ; See OctaMED docs for conditions about using these routines.
  20. ; Comments/questions about distribution and usage conditions
  21. ; should be directed to RBF Software. (Email: rbfsoft@cix.compulink.co.uk)
  22. ;
  23. ;============================================================================
  24.  
  25. ;****** Feature control ******
  26. ;
  27. MIDI        EQU 0    ;1 = include MIDI code
  28. AUDDEV        EQU 1    ;1 = allocate channels using audio.device
  29. SYNTH        EQU 1    ;1 = include synth-sound handler
  30. CHECK        EQU 1    ;1 = do range checkings (track, sample in mem etc.)
  31. RELVOL        EQU 1    ;1 = include relative volume handling code
  32. IFFMOCT        EQU 1    ;1 = play IFF multi-octave samples/ExtSamples correctly
  33. HOLD        EQU 1    ;1 = handle hold/decay
  34. PLAYMMD0    EQU 1    ;1 = play old MMD0 modules
  35. AURA        EQU 0    ;1 = support the Aura sampler
  36. ;
  37. ; The less features you include, the faster and shorter the play-routine
  38. ; will be.
  39. ;
  40. ; NOTE: Using the Aura will cause Enforcer hits (LONG-READ/WRITE at addr $70).
  41. ; This is normal, and can't be avoided.
  42.  
  43. ;****** Timing control ******
  44. ;
  45. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  46. CIAB    EQU    1    ;1 = use CIA timers (default)
  47. ;
  48. ; Please use CIAB whenever possible to avoid problems with variable
  49. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  50. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  51. ; then you just call _IntHandler for each timing pulse.
  52.  
  53. ;============================================================================
  54.  
  55. ;If you are making a demo/game with only a single tune you'd like to
  56. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  57. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  58. ;You have to insert the module name to the INCBIN statement (located near the
  59. ;end of this file, on line 2052).
  60.  
  61. EASY    EQU    0
  62.  
  63. ;Call _startmusic to play the music, and _endmusic to stop it (before
  64. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  65. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  66. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  67.  
  68. ;============================================================================
  69.  
  70. ; The MMD structure offsets
  71. mmd_id        EQU    0
  72. mmd_modlen    EQU    4
  73. mmd_songinfo    EQU    8
  74. ; these two for MMD2s only!
  75. mmd_psecnum    EQU    12
  76. mmd_pseq    EQU    14
  77. ;
  78. mmd_blockarr    EQU    16
  79. mmd_smplarr    EQU    24
  80. mmd_expdata    EQU    32
  81. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  82. mmd_pblock    EQU    42
  83. mmd_pline    EQU    44
  84. mmd_pseqnum    EQU    46
  85. mmd_counter    EQU    50
  86. mmd_songsleft    EQU    51
  87.  
  88. ; The Song structure
  89. ; Instrument data here (504 bytes = 63 * 8)
  90. msng_numblocks    EQU    504
  91. msng_songlen    EQU    506
  92. msng_playseq    EQU    508
  93. msng_deftempo    EQU    764
  94. msng_playtransp    EQU    766
  95. msng_flags    EQU    767
  96. msng_flags2    EQU    768
  97. msng_tempo2    EQU    769
  98. ; msng_trkvol applies to MMD0/MMD1 only.
  99. msng_trkvol    EQU    770
  100. msng_mastervol    EQU    786
  101. msng_numsamples    EQU    787
  102. ; Fields below apply to MMD2 modules only.
  103. msng_pseqs    EQU    508
  104. msng_sections    EQU    512
  105. msng_trkvoltbl    EQU    516
  106. msng_numtracks    EQU    520
  107. msng_numpseqs    EQU    522
  108.  
  109. ; Instrument data
  110. inst_repeat    EQU    0
  111. inst_replen    EQU    2
  112. inst_midich    EQU    4
  113. inst_midipreset    EQU    5
  114. inst_svol    EQU    6
  115. inst_strans    EQU    7
  116.  
  117. ; Audio hardware offsets
  118. ac_ptr    EQU    $00
  119. ac_len    EQU    $04
  120. ac_per    EQU    $06
  121. ac_vol    EQU    $08
  122.  
  123. ; Trackdata sizes
  124. T03SZ        EQU    106
  125. T415SZ        EQU    22
  126. ;offset of trk_audioaddr
  127. TAAOFFS        EQU    24
  128. TTMPVOLOFFS    EQU    102
  129.  
  130. ; Maximum number of tracks allowed. If you don't need this much tracks,
  131. ; you can decrease the number to save some space. (Be sure that the
  132. ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
  133. ; value = 4.)
  134. MAX_NUMTRACKS    EQU    64
  135.  
  136. ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
  137. ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
  138. MAX_MMD1_TRACKS    EQU    16
  139.  
  140. ; Aura output handling routines
  141.     IFNE    AURA
  142.         ;also includes the SECTION cmd...
  143.         INCLUDE    "aura.a"
  144.     ENDC
  145.     IFEQ    AURA
  146.         SECTION    "text",CODE
  147.     ENDC
  148.  
  149.     IFNE    EASY
  150.  
  151.         XDEF    _startmusic,_endmusic
  152.  
  153. _startmusic    lea    easymod,a2
  154.         bsr.s    _RelocModule
  155.         bsr.w    _InitPlayer
  156.         lea    easymod,a0
  157.         bra.w    _PlayModule
  158.  
  159. _endmusic    bra.w    _RemPlayer
  160. ; ***** The relocation routine *****
  161. reloci        move.l    24(a2),d0
  162.         beq.s    xloci
  163.         movea.l    d0,a0
  164.         moveq   #0,d0
  165.         move.b  msng_numsamples(a1),d0
  166.         subq.b  #1,d0
  167. relocs        bsr.s   relocentr
  168.         move.l    -4(a0),d3
  169.         beq.s    nosyn
  170.         move.l    d3,a3
  171.         tst.w    4(a3)
  172.         bpl.s    nosyn
  173.         move.w    20(a3),d2
  174.         lea    278(a3),a3
  175.         subq.w    #1,d2
  176. relsyn        add.l    d3,(a3)+
  177.         dbf    d2,relsyn
  178. nosyn        dbf     d0,relocs
  179. xloci        rts
  180. norel        addq.l    #4,a0
  181.         rts
  182. relocentr    tst.l   (a0)
  183.         beq.s   norel
  184.         add.l   d1,(a0)+
  185.         rts
  186. _RelocModule    movem.l    a2-a4/d2-d4,-(sp)
  187.         move.l  a2,d1
  188.         bsr.s    relocp
  189.         movea.l mmd_songinfo(a2),a1
  190.         bsr.s    reloci
  191.         move.b    mmd_songsleft(a2),d4
  192. rel_lp        bsr.s    relocb
  193.         cmp.b    #'2',3(a2)
  194.         bne.s    norelmmd2
  195.         bsr.w    relocmmd2sng
  196. norelmmd2    move.l    mmd_expdata(a2),d0
  197.         beq.s    rel_ex
  198.         move.l    d0,a0
  199.         bsr.s    relocentr
  200.         bsr.s    relocentr
  201.         addq.l    #4,a0
  202.         bsr.s    relocentr
  203.         addq.l    #4,a0
  204.         bsr.s    relocentr
  205.         addq.l    #8,a0
  206.         bsr.s    relocentr
  207.         addq.l    #4,a0
  208.         bsr.s    relocentr
  209.         bsr.s    relocentr
  210.         addq.l    #4,a0
  211.         bsr.s    relocentr
  212.         bsr.s    relocmdd
  213.         subq.b    #1,d4
  214.         bcs.s    rel_ex
  215.         move.l    d0,a0
  216.         move.l    (a0),d0
  217.         beq.s    rel_ex
  218.         move.l    d0,a2
  219.         bsr.s    relocp
  220.         movea.l 8(a2),a1
  221.         bra.s    rel_lp
  222. rel_ex        movem.l    (sp)+,d2-d4/a2-a4
  223.         rts
  224. relocp        lea    mmd_songinfo(a2),a0
  225.         bsr.s    relocentr
  226.         addq.l    #4,a0
  227.         bsr.s    relocentr
  228.         addq.l    #4,a0
  229.         bsr.s    relocentr
  230.         addq.l    #4,a0
  231.         bra.s    relocentr
  232. relocb        move.l    mmd_blockarr(a2),d0
  233.         beq.s    xlocb
  234.         movea.l    d0,a0
  235.         move.w  msng_numblocks(a1),d0
  236.         subq.b  #1,d0
  237. rebl        bsr    relocentr
  238.         dbf     d0,rebl
  239.         cmp.b    #'T',3(a2)
  240.         beq.s    xlocb
  241.         cmp.b    #'1',3(a2)
  242.         bge.s    relocbi
  243. xlocb        rts
  244. relocmdd    move.l    d0,-(sp)
  245.         tst.l    -(a0)
  246.         beq.s    xlocmdd
  247.         movea.l    (a0),a0
  248.         move.w    (a0),d0
  249.         addq.l    #8,a0
  250. mddloop        beq.s    xlocmdd
  251.         bsr    relocentr
  252.         bsr.s    relocdmp
  253.         subq.w    #1,d0
  254.         bra.s    mddloop
  255. xlocmdd        move.l    (sp)+,d0
  256.         rts
  257. relocdmp    move.l    -4(a0),d3
  258.         beq.s    xlocdmp
  259.         exg.l    a0,d3
  260.         addq.l    #4,a0
  261.         bsr    relocentr
  262.         move.l    d3,a0
  263. xlocdmp        rts
  264. relocbi        move.w    msng_numblocks(a1),d0
  265.         move.l    a0,a3
  266. biloop        subq.w    #1,d0
  267.         bmi.s    xlocdmp
  268.         move.l    -(a3),a0
  269.         addq.l    #4,a0
  270.         bsr    relocentr
  271.         tst.l    -(a0)
  272.         beq.s    biloop
  273.         move.l    (a0),a0
  274.         bsr    relocentr
  275.         bsr    relocentr
  276.         addq.l    #4,a0
  277.         bsr    relocentr
  278.         tst.l    -(a0)
  279.         bne.s    relocpgtbl
  280.         bra.s    biloop
  281. relocmmd2sng    move.l    mmd_songinfo(a2),a0
  282.         lea    msng_pseqs(a0),a0
  283.         bsr    relocentr
  284.         bsr    relocentr
  285.         bsr    relocentr
  286.         move.w    2(a0),d0
  287.         move.l    -12(a0),a0
  288.         subq.w    #1,d0
  289. psqtblloop    bsr    relocentr
  290.         dbf    d0,psqtblloop
  291.         rts
  292. relocpgtbl    movea.l    (a0),a4
  293.         move.w    (a4),d2
  294.         subq.w    #1,d2
  295.         lea    4(a4),a0
  296. pgtblloop    bsr    relocentr
  297.         dbf    d2,pgtblloop
  298.         bra    biloop
  299.     ENDC
  300.  
  301. ; -------- _ChannelOff: Turn off a channel -------------------------------
  302. _ChannelOff:    ;d0 = channel #
  303.         lea    DB,a0
  304.         lea    trackdataptrs-DB(a0),a1
  305.         lsl.w    #2,d0
  306.         adda.w    d0,a1
  307.         lsr.w    #2,d0
  308.         movea.l    (a1),a1
  309.         move.b    trk_outputdev(a1),d1
  310.     IFNE    AURA
  311.         beq.s    choff_outstd
  312.         subq.b    #1,d1
  313.         bne.s    notamigatrk    ;unknown type... do nothing
  314.         jmp    _StopAura(pc)    ;AURA off
  315. choff_outstd
  316.     ENDC
  317.     IFEQ    AURA
  318.         bne.s    notamigatrk
  319.     ENDC
  320.     IFNE    MIDI
  321.         move.b    trk_prevmidin(a1),d1    ;first: is it MIDI??
  322.         beq.s    notcomidi    ;not a midi note
  323. ; -------- TURN OFF MIDI TRACK -------------------------------------------
  324.         lea    noteondata-DB(a0),a0
  325. choff_midi:    clr.b    trk_prevmidin(a1)
  326.         move.b    d1,1(a0)
  327.         bmi.s    notamigatrk
  328.         move.b    trk_prevmidich(a1),(a0)    ;prev midi channel
  329.         clr.b    2(a0)
  330.         or.b    #$90,(a0)        ;note off
  331.         moveq    #3,d0
  332.         bra.w    _AddMIDIData
  333.     ENDC
  334. notcomidi:    cmp.b    #4,d0
  335.         bge.s    notamigatrk
  336. ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
  337.     IFNE    SYNTH
  338.         clr.l    trk_synthptr(a1)
  339.         clr.b    trk_synthtype(a1)
  340.     ENDC
  341.         clr.w    trk_soffset(a1)
  342.         moveq    #1,d1
  343.         lsl.w    d0,d1
  344.         move.w    d1,$dff096
  345. notamigatrk:    rts
  346.  
  347. ; -------- SoundOff: Turn off all channels -------------------------------
  348. SoundOff:    move.l    d2,-(sp)
  349.         moveq    #MAX_NUMTRACKS-1,d2
  350. SO_loop0    move.l    d2,d0
  351.         bsr.s    _ChannelOff
  352.         dbf    d2,SO_loop0
  353.         clr.l    _module        ;play nothing
  354.         move.l    (sp)+,d2
  355. SO_rts        rts
  356.  
  357. ; -------- _PlayNote: The note playing routine ---------------------------
  358. _PlayNote:    ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  359. ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
  360.         move.l    a3,d4
  361.         beq.s    SO_rts
  362.         moveq    #0,d4
  363.         bset    d7,d4    ;d4 is mask for this channel
  364.         movea.l    mmd_smplarr(a2),a0
  365.         add.w    d3,d3            ;d3 = instr.num << 2
  366.         add.w    d3,d3
  367.         move.l    0(a0,d3.w),d5        ;get address of instrument
  368.     IFNE    MIDI
  369.         bne.s    inmem
  370.         tst.b    inst_midich(a3)        ;is MIDI channel set?
  371.     ENDC
  372.     IFNE    CHECK
  373.         beq.w    pnote_rts        ; NO!!!
  374.     ENDC
  375. ; -------- ADD TRANSPOSE -------------------------------------------------
  376. inmem        add.b    msng_playtransp(a4),d1    ;add play transpose
  377.         add.b    inst_strans(a3),d1    ;and instr. transpose
  378.     IFNE    AURA
  379.         cmp.w    #3,d7
  380.         bne.s    pn_norelch3
  381.         tst.b    playing_aura-DB(a6)
  382.         bne.s    pn_offaura
  383. pn_norelch3
  384.     ENDC
  385.         move.b    trk_outputdev(a5),d3
  386.         beq.s    pn_offami
  387.     IFNE    AURA
  388.         subq.b    #1,d3
  389.         bne.s    noprevmidi
  390. pn_offaura    jsr    _StopAura(pc)
  391.     ENDC
  392.         bra.s    noprevmidi        ;dunno.. unsupported type
  393.     
  394. ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
  395. pn_offami    cmp.b    #4,d7
  396.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  397.         move.l    d5,a1
  398.     IFNE    SYNTH
  399.         tst.l    d5
  400.         beq.s    stpdma
  401.         tst.b    trk_synthtype(a5)
  402.         ble.s    stpdma        ;prev. type = sample/hybrid
  403.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  404.         beq.s    nostpdma
  405.     ENDC
  406. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  407. nostpdma:
  408.     IFNE    SYNTH
  409.         clr.l    trk_synthptr(a5)
  410.     ENDC
  411. nodmaoff:    subq.b    #1,d1
  412.     IFNE    MIDI
  413. ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
  414.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  415.         beq.s    noprevmidi
  416.         clr.b    trk_prevmidin(a5)
  417.         lea    noteondata+2-DB(a6),a0
  418.         clr.b    (a0)
  419.         move.b    d3,-(a0)
  420.         bmi.s    noprevmidi
  421.         move.b    trk_prevmidich(a5),-(a0) ;prev midi channel
  422.         or.b    #$90,(a0)         ;note off
  423.         move.w    d1,-(sp)
  424.         moveq    #3,d0
  425.         bsr.w    _AddMIDId
  426.         move.w    (sp)+,d1
  427. noprevmidi
  428. ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
  429.         tst.b    inst_midich(a3)
  430.         bne.w    handleMIDInote
  431.     ENDC
  432. ; -------- TEST OUTPUT DEVICE AND BRANCH IF NOT STD ----------------------
  433.     IFEQ    MIDI
  434. noprevmidi
  435.     ENDC
  436.         tst.b    trk_outputdev(a5)
  437.         bne.w    handlenonstdout
  438. ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
  439.     IFNE    CHECK
  440.         cmp.w    #4,d7        ;track > 3???
  441.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  442.     ENDC
  443. ; handle decay (for tracks 0 - 3 only!!)
  444.     IFNE    HOLD
  445.         clr.b    trk_fadespd(a5)        ;no fade yet..
  446.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  447.     ENDC
  448.         clr.w    trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  449.         or.w    d4,dmaonmsk-DB(a6)
  450.         move.l    d5,a0
  451.     IFNE    SYNTH
  452. ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
  453.         tst.w    4(a0)
  454.         bmi.w    handleSynthnote
  455.         clr.b    trk_synthtype(a5)
  456.     ENDC
  457. ; -------- CHECK NOTE RANGE ----------------------------------------------
  458. tlwtst0        tst.b    d1
  459.         bpl.s    notenot2low
  460.         add.b    #12,d1    ;note was too low, octave up
  461.         bra.s    tlwtst0
  462. notenot2low    cmp.b    #62,d1
  463.         ble.s    endpttest
  464.         sub.b    #12,d1    ;note was too high, octave down
  465. endpttest
  466.         moveq    #0,d2
  467.         moveq    #0,d3
  468.         moveq    #6,d4    ;skip (stereo+hdr) offset
  469.         lea    _periodtable+32-DB(a6),a1
  470.         move.b    trk_finetune(a5),d2    ;finetune value
  471.         add.b    d2,d2
  472.         add.b    d2,d2        ;multiply by 4...
  473.         ext.w    d2        ;extend
  474.         movea.l    0(a1,d2.w),a1    ;period table address
  475.         move.w    4(a0),d0    ;(Instr hdr in a0)
  476.         btst    #5,d0
  477.         beq.s    gid_nostereo
  478.         move.b    d7,d5
  479.         and.b    #3,d5
  480.         beq.s    gid_nostereo    ;ch 0/4 = play left (norm.)
  481.         cmp.b    #3,d5
  482.         beq.s    gid_nostereo    ;also for ch 3/7
  483.         add.l    (a0),d4        ;play right channel
  484. gid_nostereo
  485.     IFNE    IFFMOCT
  486.         and.w    #$F,d0
  487.         bne.s    gid_notnormal    ;note # in d1 (0 - ...)
  488.     ENDC
  489. gid_cont_ext    move.l    a1,trk_periodtbl(a5)
  490.         add.b    d1,d1
  491.         move.w    0(a1,d1.w),d5 ;put period to d5
  492.         move.l    a0,d0
  493.         move.l    (a0),d1        ;length
  494.         add.l    d4,d0        ;skip hdr and stereo
  495.         add.l    d0,d1        ;sample end pointer
  496.         move.w    inst_repeat(a3),d2
  497.         move.w    inst_replen(a3),d3
  498.     IFNE    IFFMOCT
  499.         bra    gid_setrept
  500. gid_addtable    dc.b    0,6,12,18,24,30
  501. gid_divtable    dc.b    31,7,3,15,63,127
  502. gid_notnormal    cmp.w    #7,d0
  503.         blt.s    gid_not_ext
  504.         suba.w    #48,a1
  505.         bra.s    gid_cont_ext
  506. gid_not_ext    move.l    d7,-(sp)
  507.         moveq    #0,d7
  508.         move.w    d1,d7
  509.         divu    #12,d7    ;octave #
  510.         move.l    d7,d5
  511.         cmp.w    #6,d7    ;if oct > 5, oct = 5
  512.         blt.s    nohioct
  513.         moveq    #5,d7
  514. nohioct        swap    d5    ;note number in this oct (0-11) is in d5
  515.         move.l    (a0),d1
  516.         cmp.w    #6,d0
  517.         ble.s    nounrecit
  518.         moveq    #6,d0
  519. nounrecit    add.b    gid_addtable-1(pc,d0.w),d7
  520.         move.b    gid_divtable-1(pc,d0.w),d0
  521.         divu    d0,d1    ;get length of the highest octave
  522.         swap    d1
  523.         clr.w    d1
  524.         swap    d1
  525.         move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  526.         move.w    inst_repeat(a3),d2
  527.         move.w    inst_replen(a3),d3
  528.         moveq    #0,d6
  529.         move.b    shiftcnt(pc,d7.w),d6
  530.         lsl.w    d6,d2
  531.         lsl.w    d6,d3
  532.         lsl.w    d6,d1
  533.         move.b    mullencnt(pc,d7.w),d6
  534.         mulu    d6,d0        ;offset of this oct from 1st oct
  535.         add.l    a0,d0        ;add base address to offset
  536.         add.l    d4,d0        ;skip header + stereo
  537.         add.l    d0,d1
  538.         move.l    a1,trk_periodtbl(a5)
  539.         add.b    octstart(pc,d7.w),d5
  540.         add.b    d5,d5
  541.         move.w    0(a1,d5.w),d5
  542.         move.l    (sp)+,d7
  543.         bra.s    gid_setrept
  544. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
  545.         dc.b    3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
  546. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
  547.         dc.b    7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
  548. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
  549.         dc.b    0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
  550.     ENDC
  551. gid_setrept    add.l    d2,d2
  552.         add.l    d0,d2        ;rep. start pointer
  553.         cmp.w    #1,d3
  554.         bhi.s    gid_noreplen2
  555.         moveq    #0,d3        ;no repeat
  556.         bra.s    gid_cont
  557. gid_noreplen2    add.l    d3,d3
  558.         add.l    d2,d3        ;rep. end pointer
  559.  
  560. ; -------- CALCULATE START/END ADDRESSES ---------------------------------
  561. gid_cont    moveq    #0,d4
  562.         move.w    trk_soffset(a5),d4
  563.         add.l    d4,d0
  564.         cmp.l    d0,d1
  565.         bhi.s    pn_nooffsovf
  566.         sub.l    d4,d0
  567. pn_nooffsovf    movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  568.         move.l    d0,(a1)+        ;push ac_ptr
  569.         moveq    #0,d4
  570.         move.b    trk_previnstr(a5),d4
  571.         lea    flags-DB(a6),a0
  572.         btst    #0,0(a0,d4.w)        ;test flags.SSFLG_LOOP
  573.         bne.s    repeat
  574.         
  575.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  576.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  577.         sub.l    d0,d1
  578.         lsr.l    #1,d1            ;shift length right
  579.         move.w    d1,(a1)+        ;and push to ac_len
  580.         bra.s    retsn1
  581.  
  582. repeat        move.l    d2,trk_sampleptr(a5)
  583.         move.l    d3,d1
  584.         sub.l    d0,d1
  585.         lsr.l    #1,d1
  586.         move.w    d1,(a1)+    ;ac_len
  587.         sub.l    d2,d3
  588.         lsr.l    #1,d3
  589.         move.w    d3,trk_samplelen(a5)
  590.                 
  591. retsn1        move.w    d5,trk_prevper(a5)
  592.     IFNE    SYNTH
  593.         tst.b    trk_synthtype(a5)
  594.         bne.w    hSn2
  595.     ENDC
  596. pnote_rts    rts
  597.  
  598. handlenonstdout
  599.     IFNE    AURA
  600.         move.b    trk_outputdev(a5),d0
  601.         subq.b    #1,d0
  602.         bne.s    hnso_notaura
  603. ; -------- AURA NOTE PLAYER ROUTINE --------------------------------------
  604. ;    a0 = sample pointer, already set
  605.         moveq    #0,d0
  606.         move.w    trk_soffset(a5),d0
  607.         lea    _periodtable+32-DB(a6),a1
  608.         move.b    trk_finetune(a5),d2    ;finetune value
  609.         add.b    d2,d2
  610.         add.b    d2,d2
  611.         ext.w    d2
  612.         movea.l    0(a1,d2.w),a1        ;period table address
  613.         add.b    d1,d1
  614.         move.w    0(a1,d1.w),d1
  615.         moveq    #0,d2            ;end offset = 0
  616.         jsr    _PlayAura(pc)
  617. hnso_notaura
  618.     ENDC
  619.         rts
  620.  
  621.     IFNE    MIDI
  622. ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
  623. handleMIDInote:
  624.     IFNE    PLAYMMD0
  625.         cmp.b    #'1',3(a2)
  626.         bge.s    plr_mmd1_3
  627.         add.b    #24,d1
  628. plr_mmd1_3
  629.     ENDC
  630. ; -------- CHECK & SCALE VOLUME ------------------------------------------
  631.         move.b    trk_prevvol(a5),d2 ;temporarily save the volume
  632.     IFNE    RELVOL
  633. ; -------- GetRelVol: Calculate track volume -----------------------------
  634.         ext.w    d2
  635.         mulu    trk_trackvol(a5),d2
  636.         lsr.w    #7,d2
  637.     ENDC
  638.     IFEQ    RELVOL
  639.         lsl.b    #1,d2
  640.     ENDC
  641.         subq.b    #1,d2        ;if 128 => 127
  642.         bpl.s    hmn_notvolu0
  643.         moveq    #0,d2
  644. hmn_notvolu0
  645.         moveq    #0,d5
  646. ; -------- CHECK MIDI CHANNEL --------------------------------------------
  647.         move.b    inst_midich(a3),d5 ;get midi chan of this instrument
  648.         bpl.s    hmn_nosmof    ;bit 7 clear
  649.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  650.         bra.s    hmn_smof
  651. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  652. hmn_smof    and.b    #$1F,d5        ;clear all flag bits etc...
  653.         subq.b    #1,d5        ;from 1-16 to 0-15
  654.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  655.  
  656. ; -------- CHECK MIDI PRESET ---------------------------------------------
  657.         moveq    #0,d0
  658.         move.b    trk_previnstr(a5),d0
  659.         add.w    d0,d0
  660.         lea    ext_midipsets-DB(a6),a1
  661.         move.w    0(a1,d0.w),d0    ;get preset #
  662.         beq.s    nochgpres    ;zero = no preset
  663.         lea    prevmidicpres-DB(a6),a1
  664.         adda.w    d5,a1
  665.         adda.w    d5,a1
  666.         cmp.w    (a1),d0        ;is this previous preset ??
  667.         beq.s    nochgpres    ;yes...no need to change
  668.         move.w    d0,(a1)        ;save preset to prevmidicpres
  669.         subq.w    #1,d0        ;sub 1 to get 0 - 127
  670.         btst    #6,inst_midich(a3)
  671.         bne.s    hmn_extpreset
  672. ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
  673. hmn_ordpreset    lea    preschgdata+1-DB(a6),a0
  674.         move.b    d0,(a0)        ;push the number to second byte
  675.         moveq    #2,d0
  676. hmn_sendpreset    move.b    #$c0,-(a0)    ;command: $C
  677.         or.b    d5,(a0)        ;"or" midi channel
  678.         move.w    d1,-(sp)
  679.         bsr.w    _AddMIDId
  680.         move.w    (sp)+,d1
  681.         tst.b    d2
  682.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  683.  
  684. ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
  685. nochgpres    lea    bytesinnotebuff-DB(a6),a0
  686.         movea.l    a0,a1
  687.         adda.w    (a0)+,a0
  688.         or.b    #$90,d5        ;MIDI: Note on
  689.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  690.         move.b    d1,(a0)+    ;MIDI msg note #
  691.         move.b    d2,(a0)        ;MIDI msg volume
  692.         beq.s    hmn_suppress    ;vol = 0 -> no note
  693.         addq.w    #3,(a1)
  694.         rts
  695. hmn_suppress    st    trk_prevmidin(a5)
  696.         rts
  697.  
  698. ; -------- HANDLE EXTENDED PRESET ----------------------------------------
  699. hmn_extpreset    cmp.w    #100,d0
  700.         blt.s    hmn_ordpreset
  701.         moveq    #99,d3
  702. hmn_loop100    sub.w    #100,d0
  703.         addq.b    #1,d3
  704.         cmp.w    #100,d0
  705.         bge.s    hmn_loop100
  706.         lea    preschgdata+2-DB(a6),a0
  707.         move.b    d0,(a0)        ;push the <= 99 number
  708.         move.b    d3,-(a0)    ;push the >= 100 number
  709.         moveq    #3,d0
  710.         bra.s    hmn_sendpreset
  711.     ENDC
  712.  
  713.     IFNE    SYNTH
  714. ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
  715. handleSynthnote    move.b    d1,trk_prevnote2(a5)
  716.         move.l    a0,trk_synthptr(a5)
  717.         cmp.w    #-2,4(a0)    ;HYBRID??
  718.         bne.s    hSn_nossn
  719.         st    trk_synthtype(a5)
  720.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  721.         bra.w    tlwtst0        ;go and play it
  722. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  723.         lea    _periodtable+32-DB(a6),a1
  724.         move.b    trk_finetune(a5),d0    ;finetune value
  725.         add.b    d0,d0
  726.         add.b    d0,d0        ;multiple by 4...
  727.         ext.w    d0        ;extend
  728.         movea.l    0(a1,d0.w),a1    ;period table address
  729.         suba.w    #48,a1
  730.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  731.         add.w    d1,d1
  732.         move.w    0(a1,d1.w),d1
  733.         move.w    d1,trk_prevper(a5)
  734.         clr.l    trk_sampleptr(a5)
  735. hSn2:        lea    trk_arpgoffs(a5),a1
  736.         clr.l    (a1)+
  737.         clr.l    (a1)+
  738.         btst    #0,trk_miscflags(a5)
  739.         bne.s    hSn_cmdE ;cmd E given, don't clear trk_wfcmd!
  740.         clr.w    (a1)
  741. hSn_cmdE    addq.l    #2,a1
  742.         clr.w    (a1)+
  743.         clr.l    (a1)+
  744.         clr.l    (a1)+
  745.         clr.l    (a1)+
  746.         move.l    #sinetable,(a1)+
  747.         clr.w    (a1)+
  748.         movea.l    trk_synthptr(a5),a0
  749.                 move.w    18(a0),(a1)+
  750.                 clr.b    (a1)
  751.         moveq    #64,d4
  752.         rts
  753.  
  754. synth_start    move.w    trk_prevper(a5),d5
  755. synth_start2    move.l    a3,-(sp)    ;d0 = SynthPtr
  756.         move.l    d0,a0
  757.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  758. ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
  759.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  760.         bgt.w    synth_wftbl        ;not 0...go to waveform
  761.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  762.         move.b    trk_volchgspd(a5),d0    ;volume change??
  763.         beq.s    synth_nochgvol        ;no.
  764.         add.b    trk_synvol(a5),d0    ;add previous volume
  765.         bpl.s    synth_voln2l        ;not negative
  766.         moveq    #0,d0            ;was negative => 0
  767. synth_voln2l    cmp.b    #$40,d0            ;too high??
  768.         ble.s    synth_voln2h        ;not 2 high.
  769.         moveq    #$40,d0            ;was 2 high => 64
  770. synth_voln2h    move.b    d0,trk_synvol(a5)    ;remember new...
  771. synth_nochgvol    move.l    trk_envptr(a5),d1    ;envelope pointer
  772.         beq.s    synth_novolenv
  773.         movea.l    d1,a1
  774.         move.b    (a1)+,d0
  775.         add.b    #128,d0
  776.         lsr.b    #2,d0
  777.         move.b    d0,trk_synvol(a5)
  778.         addq.b    #1,trk_envcount(a5)
  779.         bpl.s    synth_endenv
  780.         clr.b    trk_envcount(a5)
  781.         move.l    trk_envrestart(a5),a1
  782. synth_endenv    move.l    a1,trk_envptr(a5)
  783. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  784.         tst.b    trk_volwait(a5)        ;WAI(t) active
  785.         beq.s    synth_getvolcmd        ;no
  786.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  787.         ble.s    synth_getvolcmd        ;0 => continue
  788.         bra.w    synth_wftbl        ;> 0 => still wait
  789. synth_inccnt    addq.b    #1,d0
  790. synth_getvolcmd    addq.b    #1,d0            ;advance pointer
  791.         move.b    21(a0,d0.w),d1        ;get command
  792.         bmi.s    synth_cmd        ;negative = command
  793.         move.b    d1,trk_synvol(a5)    ;set synthvol
  794.         bra.w    synth_endvol        ;end of volume executing
  795. synth_cmd    and.w    #$000f,d1
  796.         add.b    d1,d1
  797.         move.w    synth_vtbl(pc,d1.w),d1
  798.         jmp    syv(pc,d1.w)
  799. synth_vtbl    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  800.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  801.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  802.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  803.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  804. ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
  805. syv
  806. syv_fe        move.b    22(a0,d0.w),d0        ;JMP
  807.         bra.s    synth_getvolcmd
  808. syv_f0        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  809.         bra.s    synth_inccnt
  810. syv_f1        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  811.         addq.b    #1,d0
  812.         bra.s    synth_endvol
  813. syv_f3        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  814.         bra.s    synth_inccnt
  815. syv_f2        move.b    22(a0,d0.w),d1
  816.         neg.b    d1
  817.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  818.         bra.s    synth_inccnt
  819. syv_fa        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  820.         clr.b    trk_wfwait(a5)
  821.         bra.s    synth_inccnt
  822. syv_f4        move.b    22(a0,d0.w),d1
  823.         bsr.s    synth_getwf
  824.         clr.l    trk_envrestart(a5)
  825. syv_f4end    move.l    a1,trk_envptr(a5)
  826.         clr.b    trk_envcount(a5)
  827.         bra.w    synth_inccnt
  828. syv_f5        move.b    22(a0,d0.w),d1
  829.         bsr.s    synth_getwf
  830.         move.l    a1,trk_envrestart(a5)
  831.         bra.s    syv_f4end
  832. syv_f6        clr.l    trk_envptr(a5)
  833.         bra.w    synth_getvolcmd
  834. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  835.         add.w    d1,d1    ;create index
  836.         add.w    d1,d1
  837.         lea    278(a0),a1
  838.         adda.w    d1,a1
  839.         movea.l    (a1),a1        ;get wform address
  840.         addq.l    #2,a1        ;skip length
  841.         rts
  842. syv_ff        subq.b    #1,d0
  843. synth_endvol    move.w    d0,trk_volcmd(a5)
  844. synth_wftbl    moveq    #0,d0
  845.         move.b    trk_synvol(a5),d0
  846.         moveq    #0,d1
  847.         move.b    trk_prevvol(a5),d1
  848.         mulu    d0,d1
  849.         asr.w    #6,d1
  850.         move.b    d1,trk_tempvol(a5)
  851.         adda.w    #158,a0
  852. ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
  853.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  854.         bgt.w    synth_arpeggio        ;not yet...
  855.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  856.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  857.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  858.         beq.s    synth_tstwfwai        ;0 = no change
  859. wytanwet    add.w    trk_perchg(a5),d1    ;add value to current change
  860.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  861. synth_tstwfwai    tst.b    trk_wfwait(a5)        ;WAI ??
  862.         beq.s    synth_getwfcmd        ;not waiting...
  863.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  864.         beq.s    synth_getwfcmd        ;waiting finished
  865.         bra.w    synth_arpeggio        ;still sleep...
  866. synth_incwfc    addq.b    #1,d0
  867. synth_getwfcmd    addq.b    #1,d0            ;advance position counter
  868.         move.b    -9(a0,d0.w),d1        ;get command
  869.         bmi.s    synth_wfcmd        ;negative = command
  870.         ext.w    d1
  871.         add.w    d1,d1
  872.         add.w    d1,d1
  873.         movea.l    120(a0,d1.w),a1
  874.         move.w    (a1)+,ac_len(a3)    ;push waveform length
  875.         move.l    a1,ac_ptr(a3)        ;and the new pointer
  876.         bra.w    synth_wfend        ;no new commands now...
  877. synth_wfcmd    and.w    #$000f,d1        ;get the right nibble
  878.         add.b    d1,d1            ;* 2
  879.         move.w    synth_wfctbl(pc,d1.w),d1
  880.         jmp    syw(pc,d1.w)        ;jump to command
  881. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  882.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  883.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  884.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  885. ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
  886. syw
  887. syw_f7        move.b    -8(a0,d0.w),d1
  888.         ext.w    d1
  889.         add.w    d1,d1
  890.         add.w    d1,d1
  891.         movea.l    120(a0,d1.w),a1
  892.         addq.l    #2,a1
  893.         move.l    a1,trk_synvibwf(a5)
  894.         bra.s    synth_incwfc
  895. syw_fe        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  896.         bra.s    synth_getwfcmd
  897. syw_fc        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  898.         move.w    d0,trk_arpgoffs(a5)
  899. synth_findare    addq.b    #1,d0
  900.         tst.b    -9(a0,d0.w)
  901.         bpl.s    synth_findare
  902.         bra.s    synth_getwfcmd
  903. syw_f0        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  904.         bra    synth_incwfc
  905. syw_f1        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  906.         addq.b    #1,d0
  907.         bra.s    synth_wfend
  908. syw_f4        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  909.         bra.w    synth_incwfc
  910. syw_f5        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  911.         addq.b    #1,trk_synthvibspd+1(a5)
  912.         bra.w    synth_incwfc
  913. syw_f2        moveq    #0,d1            ;set slide down
  914.         move.b    -8(a0,d0.w),d1
  915. synth_setsld    move.w    d1,trk_wfchgspd(a5)
  916.         bra.w    synth_incwfc
  917. syw_f3        move.b    -8(a0,d0.w),d1        ;set slide up
  918.         neg.b    d1
  919.         ext.w    d1
  920.         bra.s    synth_setsld
  921. syw_f6        clr.w    trk_perchg(a5)        ;reset period
  922.         move.w    trk_prevper(a5),d5
  923.         bra.w    synth_getwfcmd
  924. syw_fa        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  925.         clr.b    trk_volwait(a5)
  926.         bra.w    synth_incwfc
  927. syw_ff        subq.b    #1,d0        ;pointer = END - 1
  928. synth_wfend    move.w    d0,trk_wfcmd(a5)
  929. ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
  930. synth_arpeggio    move.w    trk_arpgoffs(a5),d0
  931.         beq.s    synth_vibrato
  932.         moveq    #0,d1
  933.         move.b    -8(a0,d0.w),d1
  934.         add.b    trk_prevnote2(a5),d1
  935.         movea.l    trk_periodtbl(a5),a1    ;get period table
  936.         add.w    d1,d1
  937.         move.w    0(a1,d1.w),d5
  938.         addq.b    #1,d0
  939.         tst.b    -8(a0,d0.w)
  940.         bpl.s    synth_noarpres
  941.         move.w    trk_arpsoffs(a5),d0
  942. synth_noarpres    move.w    d0,trk_arpgoffs(a5)
  943. ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
  944. synth_vibrato    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  945.         beq.s    synth_rts        ;0 => no vibrato
  946.         move.w    trk_synviboffs(a5),d0    ;get offset
  947.         lsr.w    #4,d0            ;/ 16
  948.         and.w    #$1f,d0            ;sinetable offset (0-31)
  949.         movea.l trk_synvibwf(a5),a0
  950.         move.b    0(a0,d0.w),d0       ;get a byte
  951.         ext.w    d0            ;to word
  952.         muls    d1,d0            ;amplify (* depth)
  953.         asr.w    #8,d0            ;and divide by 64
  954.         add.w    d0,d5            ;add vibrato...
  955.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  956.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  957. synth_rts    add.w    trk_perchg(a5),d5
  958.         cmp.w    #113,d5            ;overflow??
  959.         bge.s    synth_pern2h
  960.         moveq    #113,d1
  961. synth_pern2h    move.l    (sp)+,a3
  962.         rts
  963.     ENDC
  964. sinetable    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  965.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  966.         dc.b    -106,-90,-71,-49,-25,0
  967.  
  968. _IntHandler:    movem.l    d2-d7/a2-a6,-(sp)
  969.     IFNE    CIAB|VBLANK
  970.         movea.l    a1,a6    ;get data base address (int_Data)
  971.     ENDC
  972.     IFEQ    CIAB|VBLANK
  973.         lea    DB,a6    ;don't expect a1 to contain DB address
  974.     ENDC
  975.         tst.b    bpmcounter-DB(a6)
  976.         bmi.s    plr_nobpm
  977.         subq.b    #1,bpmcounter-DB(a6)
  978.         ble.s    plr_bpmcnt0
  979.         bra.w    plr_exit
  980. plr_bpmcnt0    move.b    #4,bpmcounter-DB(a6)
  981. plr_nobpm    movea.l    _module-DB(a6),a2
  982.         move.l    a2,d0
  983.         beq.w    plr_exit
  984.     IFNE    MIDI
  985.         clr.b    lastcmdbyte-DB(a6)    ;no MIDI optimization
  986.     ENDC
  987.         tst.w    mmd_pstate(a2)
  988.         beq.w    plr_exit
  989.     IFNE    MIDI
  990.         clr.l    dmaonmsk-DB(a6)
  991.     ENDC
  992.     IFEQ    MIDI
  993.         clr.w    dmaonmsk-DB(a6)
  994.     ENDC
  995.         movea.l    mmd_songinfo(a2),a4
  996.         moveq    #0,d3
  997.         move.b    mmd_counter(a2),d3
  998.         addq.b    #1,d3
  999.         cmp.b    msng_tempo2(a4),d3
  1000.         bge.s    plr_pnewnote    ;play new note
  1001.         move.b    d3,mmd_counter(a2)
  1002.         bne.w    nonewnote    ;do just fx
  1003. ; --- new note!!
  1004. plr_pnewnote:    clr.b    mmd_counter(a2)
  1005.         tst.w    blkdelay-DB(a6)
  1006.         beq.s    plr_noblkdelay
  1007.         subq.w    #1,blkdelay-DB(a6)
  1008.         bne.w    nonewnote
  1009. ; --- now start to play it
  1010. ; -------- GET ADDRESS OF NOTE DATA --------------------------------------
  1011. plr_noblkdelay    move.w    mmd_pblock(a2),d0
  1012.         bsr.w    GetNoteDataAddr
  1013.         moveq    #0,d7        ;number of track
  1014.         moveq    #0,d4
  1015.     IFNE    PLAYMMD0
  1016.         cmp.b    #'1',3(a2)
  1017.         sge    d5        ;d5 set -> >= MMD1
  1018.     ENDC
  1019.         lea    trackdataptrs-DB(a6),a1
  1020. ; -------- TRACK LOOP (FOR EACH TRACK) -----------------------------------
  1021. plr_loop0:    movea.l    (a1)+,a5    ;get address of this track's struct
  1022. ; ---------------- get the note numbers
  1023.         moveq    #0,d3
  1024.     IFNE    PLAYMMD0
  1025.         tst.b    d5
  1026.         bne.s    plr_mmd1_1
  1027.         move.b    (a3)+,d0
  1028.         move.b    (a3),d3
  1029.         addq.l    #2,a3
  1030.         lsr.b    #4,d3
  1031.         bclr    #7,d0
  1032.         beq.s    plr_bseti4
  1033.         bset    #4,d3
  1034. plr_bseti4    bclr    #6,d0
  1035.         beq.s    plr_bseti5
  1036.         bset    #5,d3
  1037. plr_bseti5    move.b    d0,trk_currnote(a5)
  1038.         beq.s    plr_nngok
  1039.         move.b    d0,(a5)
  1040.         bra.s    plr_nngok
  1041. plr_mmd1_1
  1042.     ENDC
  1043.         move.b    (a3)+,d0    ;get the number of this note
  1044.         bpl.s    plr_nothinote
  1045.         moveq    #0,d0
  1046. plr_nothinote    move.b    d0,trk_currnote(a5)
  1047.         beq.s    plr_nosetprevn
  1048.         move.b    d0,(a5)
  1049. plr_nosetprevn    move.b    (a3),d3        ;instrument number
  1050.         addq.l    #3,a3        ;adv. to next track
  1051. ; ---------------- check if there's an instrument number
  1052. plr_nngok    and.w    #$3F,d3
  1053.         beq.s    noinstnum
  1054. ; ---------------- finally, save the number
  1055.         subq.b    #1,d3
  1056.         move.b    d3,trk_previnstr(a5) ;remember instr. number!
  1057. ; ---------------- get the pointer of data's of this sample in Song-struct
  1058.         move.w    d3,d0
  1059.         asl.w    #3,d3
  1060.         lea    0(a4,d3.w),a0    ;a0 contains now address of it
  1061.         move.l    a0,trk_previnstra(a5)
  1062. ; ---------------- get volume
  1063.         move.b    inst_svol(a0),trk_prevvol(a5) ;vol of this instr
  1064.         move.b    inst_strans(a0),trk_stransp(a5)
  1065. ; ---------------- remember some values of this instrument
  1066.         lea    holdvals-DB(a6),a0
  1067.         adda.w    d0,a0
  1068.     IFNE    HOLD
  1069.         move.b    (a0),trk_inithold(a5)        ;hold
  1070.         move.b    63(a0),trk_initdecay(a5)    ;decay
  1071.     ENDC
  1072.         move.b    2*63(a0),trk_finetune(a5)    ;finetune
  1073.         move.b    6*63(a0),trk_outputdev(a5)    ;output dev
  1074. ; ---------------- remember transpose
  1075.         clr.w    trk_soffset(a5)        ;sample offset
  1076.         clr.b    trk_miscflags(a5)    ;misc.
  1077. noinstnum    addq.w    #1,d7
  1078.         cmp.w    numtracks-DB(a6),d7
  1079.         blt    plr_loop0
  1080.         bsr.w    DoPreFXLoop
  1081. ; -------- NOTE PLAYING LOOP ---------------------------------------------
  1082.         moveq    #0,d7
  1083.         lea    trackdataptrs-DB(a6),a1
  1084. plr_loop2    movea.l    (a1)+,a5
  1085.         tst.b    trk_fxtype(a5)
  1086.         bne.s    plr_loop2_end
  1087.         move.b    trk_currnote(a5),d1
  1088.         beq.s    plr_loop2_end
  1089. ; ---------------- play
  1090.         move.l    a1,-(sp)
  1091.         ext.w    d1
  1092.         moveq    #0,d3
  1093.         move.b    trk_previnstr(a5),d3    ;instr #
  1094.         movea.l    trk_previnstra(a5),a3    ;instr data address
  1095.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1096.         bne.s    plr_nohold0        ;not 0 -> OK
  1097.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1098. ; ---------------- and finally:
  1099. plr_nohold0    bsr    _PlayNote        ;play it
  1100.         move.l    (sp)+,a1
  1101. plr_loop2_end    addq.w    #1,d7
  1102.         cmp.w    numtracks-DB(a6),d7
  1103.         blt.s    plr_loop2
  1104. ; -------- THE REST... ---------------------------------------------------
  1105.         bsr.s    AdvSngPtr
  1106. nonewnote    bsr.w    DoFX
  1107. plr_endfx:    bsr    _StartDMA    ;turn on DMA
  1108. plr_exit:    movem.l    (sp)+,d2-d7/a2-a6
  1109.     IFNE    VBLANK
  1110.         moveq    #0,d0
  1111.     ENDC
  1112.         rts
  1113.  
  1114. ; and advance song pointers
  1115. AdvSngPtr    move.l    mmd_pblock(a2),fxplineblk-DB(a6) ;store pline/block for fx
  1116.         move.w    nextblockline-DB(a6),d1
  1117.         beq.s    plr_advlinenum
  1118.         clr.w    nextblockline-DB(a6)
  1119.         subq.w    #1,d1
  1120.         bra.s    plr_linenumset
  1121. plr_advlinenum    move.w    mmd_pline(a2),d1    ;get current line #
  1122.         addq.w    #1,d1            ;advance line number
  1123. plr_linenumset    cmp.w    numlines-DB(a6),d1     ;advance block?
  1124.         bhi.s    plr_chgblock        ;yes.
  1125.         tst.b    nextblock-DB(a6)    ;command F00/1Dxx?
  1126.         beq.w    plr_nochgblock        ;no, don't change block
  1127. ; -------- CHANGE BLOCK? -------------------------------------------------
  1128. plr_chgblock    tst.b    nxtnoclrln-DB(a6)
  1129.         bne.s    plr_noclrln
  1130.         moveq    #0,d1            ;clear line number
  1131. plr_noclrln    tst.w    mmd_pstate(a2)        ;play block or play song
  1132.         bpl.w    plr_nonewseq        ;play block only...
  1133.         cmp.b    #'2',3(a2)        ;MMD2?
  1134.         bne.s    plr_noMMD2_0
  1135. ; ********* BELOW CODE FOR MMD2 ONLY ************************************
  1136. ; -------- CHANGE SEQUENCE -----------------------------------------------
  1137. plr_skipseq    move.w    mmd_pseq(a2),d0        ;actually stored as << 2
  1138.         movea.l    msng_pseqs(a4),a1    ;ptr to playseqs
  1139.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1140.         move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1141.         tst.b    nextblock-DB(a6)
  1142.         bmi.s    plr_noadvseq        ;Bxx sets nextblock to -1
  1143.         addq.w    #1,d0            ;advance sequence number
  1144. plr_noadvseq    cmp.w    40(a0),d0        ;is this the highest seq number??
  1145.         blt.s    plr_notagain        ;no.
  1146. ; -------- CHANGE SECTION ------------------------------------------------
  1147.         move.w    mmd_psecnum(a2),d0    ;get section number
  1148.         addq.w    #1,d0            ;increase..
  1149.         cmp.w    msng_songlen(a4),d0    ;highest section?
  1150.         blt.s    plr_nohisec
  1151.         moveq    #0,d0            ;yes.
  1152. plr_nohisec    move.w    d0,mmd_psecnum(a2)    ;push back.
  1153.         add.w    d0,d0
  1154.         movea.l    msng_sections(a4),a0    ;section table
  1155.         move.w    0(a0,d0.w),d0        ;new playseqlist number
  1156.         add.w    d0,d0
  1157.         add.w    d0,d0
  1158.         move.w    d0,mmd_pseq(a2)
  1159.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to new PlaySeq
  1160.         moveq    #0,d0            ;playseq OFFSET = 0
  1161. ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
  1162. plr_notagain    move.w    d0,mmd_pseqnum(a2)    ;remember new playseq pos
  1163.         add.w    d0,d0
  1164.         move.w    42(a0,d0.w),d0        ;get number of the block
  1165.         bpl.s    plr_changeblk    ;neg. values for future expansion
  1166.         bra.s    plr_skipseq    ;(skip them)
  1167. ; ********* BELOW CODE FOR MMD0/MMD1 ONLY *******************************
  1168. plr_noMMD2_0    move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1169.         tst.b    nextblock-DB(a6)
  1170.         bmi.s    plr_noadvseq_b        ;Bxx sets nextblock to -1
  1171.         addq.w    #1,d0            ;advance sequence number
  1172. plr_noadvseq_b    cmp.w    msng_songlen(a4),d0    ;is this the highest seq number??
  1173.         blt.s    plr_notagain_b        ;no.
  1174.         moveq    #0,d0            ;yes: restart song
  1175. plr_notagain_b    move.b    d0,mmd_pseqnum+1(a2)    ;remember new playseq-#
  1176.         lea    msng_playseq(a4),a0    ;offset of sequence table
  1177.         move.b    0(a0,d0.w),d0        ;get number of the block
  1178. ; ********* BELOW CODE FOR BOTH FORMATS *********************************
  1179. plr_changeblk
  1180.     IFNE    CHECK
  1181.         cmp.w    msng_numblocks(a4),d0    ;beyond last block??
  1182.         blt.s    plr_nolstblk        ;no..
  1183.         moveq    #0,d0            ;play block 0
  1184.     ENDC
  1185. plr_nolstblk    move.w    d0,mmd_pblock(a2)    ;store block number
  1186. plr_nonewseq    clr.w    nextblock-DB(a6)     ;clear this if F00 set it
  1187. ; ------------------------------------------------------------------------
  1188. plr_nochgblock    move.w    d1,mmd_pline(a2)    ;set new line number
  1189.  
  1190.     IFNE    HOLD
  1191.         lea    trackdataptrs-DB(a6),a5
  1192.         move.w    mmd_pblock(a2),d0    ;pblock
  1193.         bsr.w    GetBlockAddr
  1194.         move.w    mmd_pline(a2),d0    ;play line
  1195.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  1196.     IFNE    PLAYMMD0
  1197.         cmp.b    #'1',3(a2)
  1198.         bge.s    plr_mmd1_2
  1199.         move.b    (a0),d7            ;# of tracks
  1200.         move.w    d0,d1
  1201.         add.w    d0,d0    ;d0 * 2
  1202.         add.w    d1,d0    ;+ d0 = d0 * 3
  1203.         mulu    d7,d0
  1204.         lea    2(a0,d0.w),a3
  1205.         subq.b    #1,d7
  1206. plr_chkholdb    movea.l    (a5)+,a1        ;track data
  1207.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1208.         bmi.s    plr_holdendb        ;no.
  1209.         move.b    (a3),d1            ;get the 1st byte..
  1210.         bne.s    plr_hold1b
  1211.         move.b    1(a3),d1
  1212.         and.b    #$f0,d1
  1213.         beq.s    plr_holdendb        ;don't hold
  1214.         bra.s    plr_hold2b
  1215. plr_hold1b    and.b    #$3f,d1            ;note??
  1216.         beq.s    plr_hold2b        ;no, cont hold..
  1217.         move.b    1(a3),d1
  1218.         and.b    #$0f,d1            ;get cmd
  1219.         subq.b    #3,d1            ;is there command 3 (slide)
  1220.         bne.s    plr_holdendb        ;no -> end holding
  1221. plr_hold2b    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1222. plr_holdendb    addq.l    #3,a3        ;next note
  1223.         dbf    d7,plr_chkholdb
  1224.         rts
  1225. plr_mmd1_2
  1226.     ENDC
  1227.         move.w    (a0),d7        ;# of tracks
  1228.         add.w    d0,d0
  1229.         add.w    d0,d0        ;d0 = d0 * 4
  1230.         mulu    d7,d0
  1231.         lea    8(a0,d0.l),a3
  1232.         subq.b    #1,d7
  1233. plr_chkhold    movea.l    (a5)+,a1        ;track data
  1234.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1235.         bmi.s    plr_holdend        ;no.
  1236.         move.b    (a3),d1            ;get the 1st byte..
  1237.         bne.s    plr_hold1
  1238.         move.b    1(a3),d0
  1239.         and.b    #$3F,d0
  1240.         beq.s    plr_holdend        ;don't hold
  1241.         bra.s    plr_hold2
  1242. plr_hold1    and.b    #$7f,d1            ;note??
  1243.         beq.s    plr_hold2        ;no, cont hold..
  1244.         move.b    2(a3),d1
  1245.         subq.b    #3,d1            ;is there command 3 (slide)
  1246.         bne.s    plr_holdend        ;no -> end holding
  1247. plr_hold2    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1248. plr_holdend    addq.l    #4,a3        ;next note
  1249.         dbf    d7,plr_chkhold
  1250.     ENDC
  1251.         rts
  1252.  
  1253. ; *******************************************************************
  1254. ; DoPreFXLoop:    Loop and call DoPreFX
  1255. ; *******************************************************************
  1256. DoPreFXLoop:
  1257. ; -------- PRE-FX COMMAND HANDLING LOOP ----------------------------------
  1258.         moveq    #0,d5    ;command page count
  1259. plr_loop1    move.w    mmd_pblock(a2),d0
  1260.         bsr.w    GetBlockAddr
  1261.         move.w    d5,d1
  1262.         move.w    mmd_pline(a2),d2
  1263.         bsr.w    GetCmdPointer
  1264.         movea.l    a0,a3
  1265.         moveq    #0,d7    ;clear track count
  1266.         lea    trackdataptrs-DB(a6),a1
  1267. plr_loop1_1    movea.l    (a1)+,a5
  1268.         clr.b    trk_fxtype(a5)
  1269.         move.b    (a3),d0            ;command #
  1270.         beq.s    plr_loop1_end
  1271.         moveq    #0,d4
  1272.         move.b    1(a3),d4        ;data byte
  1273.     IFNE    PLAYMMD0
  1274.         cmp.b    #3,d6            ;if adv == 3 -> MMD0
  1275.         bne.s    doprefx_mmd12mask
  1276.         and.w    #$0F,d0
  1277.         bra.s    doprefx_mmd0maskd
  1278. doprefx_mmd12mask
  1279.     ENDC
  1280.         and.w    #$1F,d0
  1281. doprefx_mmd0maskd
  1282.         bsr.s    DoPreFX
  1283.         or.b    d0,trk_fxtype(a5)
  1284. plr_loop1_end    adda.w    d6,a3            ;next track...
  1285.         addq.w    #1,d7
  1286.         cmp.w    numtracks-DB(a6),d7
  1287.         blt.s    plr_loop1_1
  1288.         addq.w    #1,d5
  1289.         cmp.w    numpages-DB(a6),d5
  1290.         bls.s    plr_loop1
  1291.         rts
  1292.  
  1293. ; *******************************************************************
  1294. ; DoPreFX: Perform effects that must be handled before note playing
  1295. ; *******************************************************************
  1296. ; args:        a6 = DB            d0 = command number (w)
  1297. ;        a5 = track data        d5 = note number
  1298. ;        a4 = song        d4 = data
  1299. ;                    d7 = track #
  1300. ; returns:    d0 = 0: play - d0 = 1: don't play
  1301.  
  1302. rtplay        MACRO
  1303.         moveq    #0,d0
  1304.         rts
  1305.         ENDM
  1306. rtnoplay    MACRO
  1307.         moveq    #1,d0
  1308.         rts
  1309.         ENDM
  1310.  
  1311. DoPreFX:    add.b    d0,d0    ;* 2
  1312.         move.w    f_table(pc,d0.w),d0
  1313.         jmp    fst(pc,d0.w)
  1314. f_table        dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1315.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  1316.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  1317.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,f_1e-fst,f_1f-fst
  1318. fst
  1319. ; ---------------- tempo (F)
  1320. f_0f        tst.b    d4        ;test effect qual..
  1321.         beq    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  1322.         cmp.b    #$f0,d4        ;..is zero, go to next block
  1323.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  1324. ; ---------------- just an ordinary "change tempo"-request
  1325.     IFNE    CIAB
  1326.         moveq    #0,d0        ;will happen!!!
  1327.         move.b    d4,d0
  1328.         bsr    _SetTempo    ;change The Tempo
  1329.     ENDC
  1330. fx        rtplay
  1331. ; ---------------- no, it was FFx, something special will happen!!
  1332. fx0fspecial:    cmp.b    #$f2,d4
  1333.         beq.s    f_1f
  1334.         cmp.b    #$f4,d4
  1335.         beq.s    f_1f
  1336.         cmp.b    #$f5,d4
  1337.         bne.s    isfxfe
  1338. ; ---------------- FF2 (or 1Fxx)
  1339. f_1f
  1340.     IFNE    HOLD
  1341.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1342.         bne.s    f_1frts            ;not 0 -> OK
  1343.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1344.     ENDC
  1345. f_1frts        rtnoplay
  1346. isfxfe:        cmp.b    #$fe,d4
  1347.         bne.s    notcmdfe
  1348. ; ---------------- it was FFE, stop playing
  1349.         clr.w    mmd_pstate(a2)
  1350.     IFNE    CIAB
  1351.         movea.l    craddr-DB(a6),a0
  1352.         bclr    #0,(a0)
  1353.     ENDC
  1354.         bsr.w    SoundOff
  1355.     IFNE    AURA
  1356.         jsr    _RemAura(pc)
  1357.     ENDC
  1358.         adda.w    #8,sp    ;2 subroutine levels
  1359.         bra.w    plr_exit
  1360. f_ffe_no8    rtplay
  1361. notcmdfe:    cmp.b    #$fd,d4 ;change period
  1362.         bne.s    isfxff
  1363. ; ---------------- FFD, change the period, don't replay the note
  1364.     IFNE    CHECK
  1365.         cmp.w    #4,d7 ;no tracks above 4, thank you!!
  1366.         bge.s    f_ff_rts
  1367.     ENDC
  1368.         move.l    trk_periodtbl(a5),d1    ;period table
  1369.         beq.s    f_1frts
  1370.         movea.l    d1,a0
  1371.         move.b    trk_currnote(a5),d0
  1372.         subq.b    #1,d0    ;sub 1 to make "real" note number
  1373.     IFNE    CHECK
  1374.         bmi.s    f_1frts
  1375.     ENDC
  1376.         add.b    msng_playtransp(a4),d0
  1377.         add.b    trk_stransp(a5),d0
  1378.         add.w    d0,d0
  1379.         bmi.s    f_1frts
  1380.         move.w    0(a0,d0.w),trk_prevper(a5) ;get & push the period
  1381.         rtnoplay
  1382. isfxff:        cmp.b    #$ff,d4        ;note off??
  1383.         bne.s    f_ff_rts
  1384.         move.w    d7,d0
  1385.         move.l    a1,-(sp)
  1386.         bsr.w    _ChannelOff
  1387.         move.l    (sp)+,a1
  1388. f_ff_rts    rtplay
  1389. ; ---------------- F00, called Pattern Break in ST
  1390. fx0fchgblck:    move.b    #1,nextblock-DB(a6) ;next block????...YES!!!! (F00)
  1391.         bra.s    f_ff_rts
  1392. ; ---------------- was not Fxx, then it's something else!!
  1393. f_0e
  1394.     IFNE    CHECK
  1395.         cmp.b    #4,d7
  1396.         bge.s    f_0e_rts
  1397.     ENDC
  1398.         bset    #0,trk_miscflags(a5)
  1399.         move.b    d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  1400. f_0e_rts    rtplay
  1401. ; ---------------- change volume
  1402. f_0c        move.b    d4,d0
  1403.         bpl.s    plr_nosetdefvol
  1404.         and.b    #$7F,d0
  1405.     IFNE    CHECK
  1406.         cmp.b    #64,d0
  1407.         bgt.s    go_nocmd
  1408.     ENDC
  1409.         moveq    #0,d1
  1410.         move.b    trk_previnstr(a5),d1
  1411.         asl.w    #3,d1
  1412.         move.b    d0,inst_svol(a4,d1.w)    ;set new svol
  1413.         bra.s    plr_setvol
  1414. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  1415.         bne.s    volhex
  1416.         lsr.b    #4,d0        ;get number from left
  1417.         mulu    #10,d0        ;number of tens
  1418.         move.b    d4,d1        ;get again
  1419.         and.b    #$0f,d1        ;this time don't get tens
  1420.         add.b    d1,d0        ;add them
  1421. volhex:
  1422.     IFNE    CHECK
  1423.         cmp.b    #64,d0
  1424.         bhi.s    go_nocmd
  1425.     ENDC
  1426. plr_setvol    move.b    d0,trk_prevvol(a5)
  1427. go_nocmd    rtplay
  1428. ; ---------------- tempo2 change??
  1429. f_09
  1430.     IFNE    CHECK
  1431.         and.b    #$1F,d4
  1432.         bne.s    fx9chk
  1433.         moveq    #$20,d4
  1434.     ENDC
  1435. fx9chk:        move.b    d4,msng_tempo2(a4)
  1436. f_09_rts    rtplay
  1437. ; ---------------- block delay
  1438. f_1e        tst.w    blkdelay-DB(a6)
  1439.         bne.s    f_1e_rts
  1440.         addq.w    #1,d4
  1441.         move.w    d4,blkdelay-DB(a6)
  1442. f_1e_rts    rtplay
  1443. ; ---------------- finetune
  1444. f_15
  1445.     IFNE    CHECK
  1446.         cmp.b    #7,d4
  1447.         bgt.s    f_15_rts
  1448.         cmp.b    #-8,d4
  1449.         blt.s    f_15_rts
  1450.     ENDC
  1451.         move.b    d4,trk_finetune(a5)
  1452. f_15_rts    rtplay
  1453. ; ---------------- repeat loop
  1454. f_16        tst.b    d4
  1455.         bne.s    plr_dorpt
  1456.         move.w    mmd_pline(a2),rptline-DB(a6)
  1457.         bra.s    f_16_rts
  1458. plr_dorpt    tst.w    rptcounter-DB(a6)
  1459.         beq.s    plr_newrpt
  1460.         subq.w    #1,rptcounter-DB(a6)
  1461.         beq.s    f_16_rts
  1462.         bra.s    plr_setrptline
  1463. plr_newrpt    move.b    d4,rptcounter+1-DB(a6)
  1464. plr_setrptline    move.w    rptline-DB(a6),d0
  1465.         addq.w    #1,d0
  1466.         move.w    d0,nextblockline-DB(a6)
  1467. f_16_rts    rtplay
  1468. ; ---------------- preset change
  1469. f_1c        cmp.b    #$80,d4
  1470.         bhi.s    f_1c_rts
  1471.         moveq    #0,d1
  1472.         move.b    trk_previnstr(a5),d1
  1473.         add.w    d1,d1
  1474.         lea    ext_midipsets-DB(a6),a0
  1475.         ext.w    d4
  1476.         move.w    d4,0(a0,d1.w)        ;set MIDI preset
  1477. f_1c_rts    rtplay
  1478. ; ---------------- note off time set??
  1479. f_08
  1480.     IFNE    HOLD
  1481.         move.b    d4,d0
  1482.         lsr.b    #4,d4        ;extract left  nibble
  1483.         and.b    #$0f,d0        ; "   "  right  "  "
  1484.         move.b    d4,trk_initdecay(a5)    ;left = decay
  1485.         move.b    d0,trk_inithold(a5)    ;right = hold
  1486.     ENDC
  1487.         rtplay
  1488. ; ---------------- sample begin offset
  1489. f_19        lsl.w    #8,d4
  1490.         move.w    d4,trk_soffset(a5)
  1491. f_19_rts    rtplay
  1492. ; ---------------- cmd Bxx, "position jump"
  1493. f_0b
  1494.     IFNE    CHECK
  1495.         cmp.b    #'2',3(a2)
  1496.         beq.s    chk0b_mmd2
  1497.         cmp.w    msng_songlen(a4),d4
  1498.         bhi.s    f_0b_rts
  1499.         bra.s    chk0b_end
  1500. chk0b_mmd2    move.w    mmd_pseq(a2),d0        ;get seq number
  1501.         movea.l    msng_pseqs(a4),a0    ;ptr to playseqs
  1502.         movea.l    0(a0,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1503.         cmp.w    40(a0),d4        ;test song length
  1504.         bhi.s    f_0b_rts
  1505. chk0b_end
  1506.     ENDC
  1507.         move.w    d4,mmd_pseqnum(a2)
  1508.         st    nextblock-DB(a6)    ; = 1
  1509. f_0b_rts    rtplay
  1510. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1511. f_1d        move.w    #$1ff,nextblock-DB(a6)
  1512.         addq.w    #1,d4
  1513.         move.w    d4,nextblockline-DB(a6)
  1514.         rtplay
  1515. ; ---------------- try portamento (3)
  1516. f_03
  1517.     IFNE    CHECK
  1518.         cmp.w    #4,d7
  1519.         bge.s    f_03_rts
  1520.     ENDC
  1521.         moveq    #0,d0
  1522.         move.b    trk_currnote(a5),d0
  1523.         subq.b    #1,d0        ;subtract note number
  1524.         bmi.s    plr_setfx3spd    ;0 -> set new speed
  1525.         move.l    trk_periodtbl(a5),d1
  1526.         beq.s    f_03_rts
  1527.         movea.l    d1,a0
  1528.         add.b    msng_playtransp(a4),d0    ;play transpose
  1529.         add.b    trk_stransp(a5),d0 ;and instrument transpose
  1530.         bmi.s    f_03_rts    ;again.. too low
  1531.         add.w    d0,d0
  1532.         move.w    0(a0,d0.w),trk_porttrgper(a5) ;period of this note is the target
  1533. plr_setfx3spd:    tst.b    d4        ;qual??
  1534.         beq.s    f_03_rts    ;0 -> do nothing
  1535.         move.b    d4,trk_prevportspd(a5)    ;store speed
  1536. f_03_rts    rtnoplay
  1537.  
  1538. ; *******************************************************************
  1539. ; DoFX: Handle effects, hold/fade etc.
  1540. ; *******************************************************************
  1541. DoFX        moveq    #0,d3
  1542.         move.b    mmd_counter(a2),d3
  1543.     IFNE    HOLD
  1544.         lea    trackdataptrs-DB(a6),a1
  1545. ; Loop 1: Hold/Fade handling
  1546.         moveq    #0,d7    ;clear track count
  1547. dofx_loop1    movea.l    (a1)+,a5
  1548.         bsr.w    HoldAndFade
  1549.         addq.w    #1,d7
  1550.         cmp.w    numtracks-DB(a6),d7
  1551.         blt.s    dofx_loop1
  1552.     ENDC
  1553. ; Loop 2: Track command handling
  1554.         moveq    #0,d5    ;command page count
  1555. dofx_loop2    move.w    fxplineblk-DB(a6),d0
  1556.         bsr.w    GetBlockAddr
  1557.         movea.l    a0,a3
  1558.     IFNE    PLAYMMD0
  1559.         cmp.b    #'1',3(a2)
  1560.         bge.s    dofx_sbd_nommd0
  1561.         bsr.w    StoreBlkDimsMMD0
  1562.         bra.s    dofx_sbd_mmd0
  1563. dofx_sbd_nommd0
  1564.     ENDC
  1565.         bsr.w    StoreBlockDims
  1566. dofx_sbd_mmd0    move.w    d5,d1
  1567.         move.w    fxplineblk+2-DB(a6),d2
  1568.         movea.l    a3,a0
  1569.         bsr.s    GetCmdPointer
  1570.         movea.l    a0,a3
  1571.         moveq    #0,d7    ;clear track count
  1572.         lea    trackdataptrs-DB(a6),a1
  1573. dofx_loop2_1    movea.l    (a1)+,a5
  1574.         moveq    #0,d4
  1575.         move.b    (a3),d0            ;command #
  1576.         move.b    1(a3),d4        ;data byte
  1577.     IFNE    PLAYMMD0
  1578.         cmp.b    #3,d6            ;if adv == 3 -> MMD0
  1579.         bne.s    dofx_mmd12mask
  1580.         and.w    #$0F,d0
  1581.         bra.s    dofx_mmd0maskd
  1582. dofx_mmd12mask
  1583.     ENDC
  1584.         and.w    #$1F,d0
  1585. dofx_mmd0maskd    tst.b    trk_fxtype(a5)
  1586.         bgt.s    dofx_lend2_1    ;1 = skip
  1587.     IFNE    MIDI
  1588.         beq.s    dofx_chfx
  1589.         bsr.w    MIDIFX
  1590.         bra.s    dofx_lend2_1
  1591.     ENDC
  1592.     IFEQ    MIDI
  1593.         bne.s    dofx_lend2_1
  1594.     ENDC
  1595. dofx_chfx    bsr.w    ChannelFX
  1596. dofx_lend2_1    adda.w    d6,a3            ;next track...
  1597.         addq.w    #1,d7
  1598.         cmp.w    numtracks-DB(a6),d7
  1599.         blt.s    dofx_loop2_1
  1600.         addq.w    #1,d5
  1601.         cmp.w    numpages-DB(a6),d5
  1602.         bls.s    dofx_loop2
  1603. ; Loop 3: Updating audio hardware
  1604.         moveq    #0,d7    ;clear track count
  1605.         lea    trackdataptrs-DB(a6),a1
  1606. dofx_loop3    movea.l    (a1)+,a5
  1607.     IFNE    HOLD
  1608.         tst.b    trk_fxtype(a5)
  1609.         bne.s    dofx_lend3    ;only in case 0 (norm)
  1610.     ENDC
  1611.     IFEQ    HOLD
  1612.         cmp.w    #4,d7
  1613.         bge.s    dofx_stopl3
  1614.     ENDC
  1615.         bsr.w    UpdatePerVol
  1616. dofx_lend3    addq.w    #1,d7
  1617.         cmp.w    numtracks-DB(a6),d7
  1618.         blt.s    dofx_loop3
  1619. dofx_stopl3    rts
  1620.  
  1621. ; *******************************************************************
  1622. ; GetCmdPointer: Return command pointer for track 0
  1623. ; *******************************************************************
  1624. ; args:        a0 = block pointer
  1625. ;        d1 = page number
  1626. ;        d2 = line number
  1627. ;        a2 = module
  1628. ; result:    a0 = command pointer (i.e. trk 0 note + 2)
  1629. ;        d6 = track advance (bytes)
  1630. ; scratches:    d0, d1, d2, a0
  1631. ; Note: no num_pages check! If numpages > 0 it can be assumed that
  1632. ; extra pages exist.
  1633.  
  1634. GetCmdPointer
  1635.     IFNE    PLAYMMD0
  1636.         cmp.b    #'1',3(a2)
  1637.         blt.s    GetCmdPtrMMD0
  1638.     ENDC
  1639.         mulu    (a0),d2        ;d2 = line # * numtracks
  1640.         add.l    d2,d2        ;d2 *= 2...
  1641.         subq.w    #1,d1
  1642.         bmi.s    gcp_page0
  1643.         movea.l    4(a0),a0
  1644.         movea.l    12(a0),a0
  1645.         add.w    d1,d1
  1646.         add.w    d1,d1
  1647.         movea.l    4(a0,d1.w),a0    ;command data
  1648.         adda.l    d2,a0
  1649.         moveq    #2,d6
  1650.         rts
  1651. gcp_page0    add.l    d2,d2        ;d2 *= 4
  1652.         lea    10(a0,d2.l),a0    ;offs: 4 = header, 2 = note
  1653.         moveq    #4,d6        ;track advance (bytes)
  1654.         rts
  1655.     IFNE    PLAYMMD0
  1656. GetCmdPtrMMD0    moveq    #0,d0
  1657.         move.b    (a0),d0        ;get numtracks
  1658.         mulu    d0,d2        ;line # * numtracks
  1659.         move.w    d2,d0
  1660.         add.w    d2,d2
  1661.         add.w    d0,d2        ; *= 3...
  1662.         lea    3(a0,d2.l),a0    ;offs: 2 = header, 1 = note
  1663.         moveq    #3,d6
  1664.         rts
  1665.     ENDC
  1666.  
  1667. ; *******************************************************************
  1668. ; GetBlockAddr: Return pointer to block
  1669. ; *******************************************************************
  1670. ; args:        d0 = block number
  1671. ; result:    a0 = block pointer
  1672. ; scratches: d0, a0
  1673.  
  1674. GetBlockAddr    movea.l    mmd_blockarr(a2),a0
  1675.         add.w    d0,d0
  1676.         add.w    d0,d0
  1677.         movea.l    0(a0,d0.w),a0
  1678.         rts
  1679.  
  1680. ; *******************************************************************
  1681. ; GetNoteDataAddr: Check & return addr. of current note
  1682. ; *******************************************************************
  1683. ;args:        d0 = pblock        a6 = DB
  1684. ;returns:    a3 = address
  1685. ;scratches:    d0, a0, d1
  1686.  
  1687. GetNoteDataAddr    bsr.w    GetBlockAddr
  1688.         movea.l    a0,a3
  1689.     IFNE    PLAYMMD0
  1690.         cmp.b    #'1',3(a2)
  1691.         blt.s    GetNDAddrMMD0
  1692.     ENDC
  1693.         bsr.w    StoreBlockDims
  1694.         move.w    numlines-DB(a6),d1
  1695.         move.w    mmd_pline(a2),d0
  1696.         cmp.w    d1,d0        ;check if block end exceeded...
  1697.         bls.s    plr_nolinex
  1698.         move.w    d1,d0
  1699. plr_nolinex    add.w    d0,d0
  1700.         add.w    d0,d0    ;d0 = d0 * 4
  1701.         mulu    numtracks-DB(a6),d0
  1702.         lea    8(a3,d0.l),a3    ;address of current note
  1703.         rts
  1704.  
  1705.     IFNE    PLAYMMD0
  1706. GetNDAddrMMD0    bsr.w    StoreBlkDimsMMD0
  1707.         move.w    numlines-DB(a6),d1
  1708.         move.w    mmd_pline(a2),d0
  1709.         cmp.w    d1,d0        ;check if block end exceeded...
  1710.         bls.s    plr_nolinex2
  1711.         move.w    d1,d0
  1712. plr_nolinex2    move.w    d0,d1
  1713.         add.w    d0,d0
  1714.         add.w    d1,d0    ;d0 = d0 * 3
  1715.         mulu    numtracks-DB(a6),d0
  1716.         lea    2(a3,d0.l),a3    ;address of current note
  1717.         rts
  1718.     ENDC
  1719.  
  1720. ; *******************************************************************
  1721. ; StoreBlockDims: Store block dimensions
  1722. ; *******************************************************************
  1723. ; args:        a0 = block ptr, a6 = DB
  1724.  
  1725. StoreBlockDims    move.l    (a0)+,numtracks-DB(a6)    ;numtracks & lines
  1726.         tst.l    (a0)            :BlockInfo
  1727.         beq.s    sbd_1page
  1728.         movea.l    (a0),a0
  1729.         move.l    12(a0),d0        ;BlockInfo.pagetable
  1730.         beq.s    sbd_1page
  1731.         movea.l    d0,a0
  1732.         move.w    (a0),numpages-DB(a6)    ;num_pages
  1733.         rts
  1734. sbd_1page    clr.w    numpages-DB(a6)
  1735.         rts
  1736.  
  1737.     IFNE    PLAYMMD0
  1738. StoreBlkDimsMMD0
  1739.         clr.w    numpages-DB(a6)
  1740.         moveq    #0,d0
  1741.         move.b    (a0)+,d0        ;numtracks
  1742.         move.w    d0,numtracks-DB(a6)
  1743.         move.b    (a0),d0            ;numlines
  1744.         move.w    d0,numlines-DB(a6)
  1745.         rts
  1746.     ENDC
  1747.  
  1748. ; *******************************************************************
  1749. ; HoldAndFade: Handle hold/fade
  1750. ; *******************************************************************
  1751. ; args:        a5 = track data
  1752. ;        a6 = DB
  1753. ;        d7 = track #
  1754. ; scratches:    d0, d1, a0
  1755.  
  1756.     IFNE    HOLD
  1757. HoldAndFade
  1758.     IFNE    MIDI
  1759.         tst.b    trk_prevmidin(a5)    ;is it MIDI??
  1760.         bne.w    plr_haf_midi
  1761.     ENDC
  1762.     IFNE    CHECK
  1763.         cmp.w    #4,d7
  1764.         bge.w    plr_haf_midi    ;no non-MIDI effects in tracks 4 - 15
  1765.     ENDC
  1766.         tst.b    trk_noteoffcnt(a5)
  1767.         bmi.s    plr_haf_noholdexp
  1768.         subq.b    #1,trk_noteoffcnt(a5)
  1769.         bpl.s    plr_haf_noholdexp
  1770.     IFNE    SYNTH
  1771.         tst.b    trk_synthtype(a5)        ;synth/hybrid??
  1772.         beq.s    plr_nosyndec
  1773.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1774.         clr.b    trk_volwait(a5)            ;abort WAI
  1775.         bra.s    plr_haf_noholdexp
  1776.     ENDC
  1777. plr_nosyndec    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1778.         bne.s    plr_haf_noholdexp        ;if > 0, don't stop sound
  1779.         moveq    #0,d0
  1780.         bset    d7,d0
  1781.         move.w    d0,$dff096            ;shut DMA...
  1782. plr_haf_noholdexp
  1783.         move.b    trk_fadespd(a5),d0    ;fade??
  1784.         beq.s    plr_haf_dofx        ;no.
  1785.         sub.b    d0,trk_prevvol(a5)
  1786.         bpl.s    plr_nofade2low
  1787.         clr.b    trk_prevvol(a5)
  1788.         clr.b    trk_fadespd(a5)        ;fade no more
  1789. plr_nofade2low
  1790. plr_haf_dofx    clr.b    trk_fxtype(a5)
  1791. plr_haf_rts    rts
  1792. ; MIDI version
  1793. plr_haf_midi
  1794.         st    trk_fxtype(a5)
  1795.     IFNE    MIDI
  1796.         tst.b    trk_noteoffcnt(a5)
  1797.         bmi.s    plr_haf_rts
  1798.         subq.b    #1,trk_noteoffcnt(a5)
  1799.         bpl.s    plr_haf_rts
  1800.         move.b    trk_prevmidin(a5),d1
  1801.         beq.s    plr_haf_rts
  1802.         lea    noteondata-DB(a6),a0
  1803.         exg.l    a5,a1
  1804.         bsr.w    choff_midi
  1805.         exg.l    a5,a1
  1806.     ENDC
  1807.         rts
  1808. ;hold
  1809.     ENDC
  1810.  
  1811. ; *******************************************************************
  1812. ; ChannelFX:    Do an effect on a channel
  1813. ; *******************************************************************
  1814. ;args:                    d3 = counter
  1815. ;        a4 = song struct    d4 = command qual (long, byte used)
  1816. ;        a5 = track data ptr    
  1817. ;        a6 = DB            d0 = command (long, byte used)
  1818. ;                    d7 = track (channel) number
  1819. ;scratches: d0, d1, d4, a0
  1820.  
  1821. ChannelFX    add.b    d0,d0    ;* 2
  1822.         move.w    fx_table(pc,d0.w),d0
  1823.         jmp    fxs(pc,d0.w)
  1824. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1825.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1826.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
  1827.         dc.w    fx_0f-fxs
  1828.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1829.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1830.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1831.         dc.w    fx_1f-fxs
  1832. fxs:
  1833. ;    **************************************** Effect 01 ******
  1834. fx_01        tst.b    d3
  1835.         bne.s    fx_01nocnt0
  1836.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1837.         bne.s    fx_01rts
  1838. fx_01nocnt0    move.w    trk_prevper(a5),d0
  1839.         sub.w    d4,d0
  1840.         cmp.w    #113,d0
  1841.         bge.s    fx_01noovf
  1842.         move.w    #113,d0
  1843. fx_01noovf    move.w    d0,trk_prevper(a5)
  1844. fx_xx        ;fx_xx is just a RTS
  1845. fx_01rts    rts
  1846. ;    **************************************** Effect 11 ******
  1847. fx_11        tst.b    d3
  1848.         bne.s    fx_11rts
  1849.         sub.w    d4,trk_prevper(a5)
  1850. fx_11rts    rts
  1851. ;    **************************************** Effect 02 ******
  1852. fx_02        tst.b    d3
  1853.         bne.s    fx_02nocnt0
  1854.         btst    #5,msng_flags(a4)
  1855.         bne.s    fx_02rts
  1856. fx_02nocnt0    add.w    d4,trk_prevper(a5)
  1857. fx_02rts    rts
  1858. ;    **************************************** Effect 12 ******
  1859. fx_12        tst.b    d3
  1860.         bne.s    fx_12rts
  1861.         add.w    d4,trk_prevper(a5)
  1862. fx_12rts    rts
  1863. ;    **************************************** Effect 00 ******
  1864. fx_00        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1865.         beq.s    fx_00rts
  1866.         move.l    d3,d0
  1867.         divu    #3,d0
  1868.         swap    d0
  1869.         subq.b    #1,d0
  1870.         bgt.s    fx_arp2
  1871.         blt.s    fx_arp0
  1872.         and.b    #$0f,d4
  1873.         bra.s    fx_doarp
  1874. fx_arp0        lsr.b    #4,d4
  1875.         bra.s    fx_doarp
  1876. fx_arp2        moveq    #0,d4
  1877. fx_doarp:    move.b    (a5),d0
  1878.         subq.b    #1,d0        ;-1 to make it 0 - 127
  1879.         add.b    msng_playtransp(a4),d0    ;add play transpose
  1880.         add.b    trk_stransp(a5),d0    ;add instrument transpose
  1881.         add.b    d0,d4
  1882.         move.l    trk_periodtbl(a5),d1
  1883.         beq.s    fx_00rts
  1884.         movea.l    d1,a0
  1885.         add.b    d0,d0
  1886.         move.w    0(a0,d0.w),d0    ;base note period
  1887.         add.b    d4,d4
  1888.         sub.w    0(a0,d4.w),d0    ;calc difference from base note
  1889.         move.w    d0,trk_arpadjust(a5)
  1890. fx_00rts    rts
  1891. ;    **************************************** Effect 04 ******
  1892. fx_14        move.b    #6,trk_vibshift(a5)
  1893.         bra.s    vib_cont
  1894. fx_04        move.b    #5,trk_vibshift(a5)
  1895. vib_cont    tst.b    d3
  1896.         bne.s    nonvib
  1897.         move.b    d4,d1
  1898.         beq.s    nonvib
  1899.         and.w    #$0f,d1
  1900.         beq.s    plr_chgvibspd
  1901.         move.w    d1,trk_vibrsz(a5)
  1902. plr_chgvibspd    and.b    #$f0,d4
  1903.         beq.s    nonvib
  1904.         lsr.b    #3,d4
  1905.         and.b    #$3e,d4
  1906.         move.b    d4,trk_vibrspd(a5)
  1907. nonvib        move.b    trk_vibroffs(a5),d0
  1908.         lsr.b    #2,d0
  1909.         and.w    #$1f,d0
  1910.         moveq    #0,d1
  1911.         lea    sinetable(pc),a0
  1912.         move.b    0(a0,d0.w),d0
  1913.         ext.w    d0
  1914.         muls    trk_vibrsz(a5),d0
  1915.         move.b    trk_vibshift(a5),d1
  1916.         asr.w    d1,d0
  1917.         move.w    d0,trk_vibradjust(a5)
  1918.         move.b    trk_vibrspd(a5),d0
  1919.         add.b    d0,trk_vibroffs(a5)
  1920. fx_04rts    rts
  1921. ;    **************************************** Effect 06 ******
  1922. fx_06:        tst.b    d3
  1923.         bne.s    fx_06nocnt0
  1924.         btst    #5,msng_flags(a4)
  1925.         bne.s    fx_04rts
  1926. fx_06nocnt0    bsr.s    plr_volslide        ;Volume slide
  1927.         bra.s    nonvib            ;+ Vibrato
  1928. ;    **************************************** Effect 07 ******
  1929. fx_07        tst.b    d3
  1930.         bne.s    nontre
  1931.         move.b    d4,d1
  1932.         beq.s    nontre
  1933.         and.w    #$0f,d1
  1934.         beq.s    plr_chgtrespd
  1935.         move.w    d1,trk_tremsz(a5)
  1936. plr_chgtrespd    and.b    #$f0,d4
  1937.         beq.s    nontre
  1938.         lsr.b    #2,d4
  1939.         and.b    #$3e,d4
  1940.         move.b    d4,trk_tremspd(a5)
  1941. nontre        move.b    trk_tremoffs(a5),d0
  1942.         lsr.b    #3,d0
  1943.         and.w    #$1f,d0
  1944.         lea    sinetable(pc),a0
  1945.         move.b    0(a0,d0.w),d1
  1946.         ext.w    d1
  1947.         muls    trk_tremsz(a5),d1
  1948.         asr.w    #7,d1
  1949.         move.b    trk_tremspd(a5),d0
  1950.         add.b    d0,trk_tremoffs(a5)
  1951.         add.b    trk_prevvol(a5),d1
  1952.         bpl.s    tre_pos
  1953.         moveq    #0,d1
  1954. tre_pos        cmp.b    #64,d1
  1955.         ble.s    tre_no2hi
  1956.         moveq    #64,d1
  1957. tre_no2hi    move.b    d1,trk_tempvol(a5)
  1958.         rts
  1959. ;    ********* VOLUME SLIDE FUNCTION *************************
  1960. plr_volslide    move.b    d4,d0
  1961.         moveq    #0,d1
  1962.         move.b    trk_prevvol(a5),d1 ;move previous vol to d1
  1963.         and.b    #$f0,d0
  1964.         bne.s    crescendo
  1965.         sub.b    d4,d1    ;sub from prev. vol
  1966. voltest0    bpl.s    novolover64
  1967.         moveq    #0,d1    ;volumes under zero not accepted
  1968.         bra.s    novolover64
  1969. crescendo:    lsr.b    #4,d0
  1970.         add.b    d0,d1
  1971. voltest        cmp.b    #64,d1
  1972.         ble.s    novolover64
  1973.         moveq    #64,d1
  1974. novolover64    move.b    d1,trk_prevvol(a5)
  1975. volsl_rts    rts
  1976. ;    **************************************** Effect 0D/0A ***
  1977. fx_0a:
  1978. fx_0d:        tst.b    d3
  1979.         bne.s    plr_volslide
  1980.         btst    #5,msng_flags(a4)
  1981.         beq.s    plr_volslide
  1982.         rts
  1983. ;    **************************************** Effect 05 ******
  1984. fx_05:        tst.b    d3
  1985.         bne.s    fx_05nocnt0
  1986.         btst    #5,msng_flags(a4)
  1987.         bne.s    fx_05rts
  1988. fx_05nocnt0    bsr.s    plr_volslide
  1989.         bra.s    fx_03nocnt0
  1990. fx_05rts    rts
  1991. ;    **************************************** Effect 1A ******
  1992. fx_1a        tst.b    d3
  1993.         bne.s    volsl_rts
  1994.         move.b    trk_prevvol(a5),d1
  1995.         add.b    d4,d1
  1996.         bra.s    voltest
  1997. ;    **************************************** Effect 1B ******
  1998. fx_1b        tst.b    d3
  1999.         bne.s    volsl_rts
  2000.         move.b    trk_prevvol(a5),d1
  2001.         sub.b    d4,d1
  2002.         bra.s    voltest0
  2003. ;    **************************************** Effect 03 ******
  2004. fx_03        tst.b    d3
  2005.         bne.s    fx_03nocnt0
  2006.         btst    #5,msng_flags(a4)
  2007.         bne.s    fx_03rts
  2008. fx_03nocnt0    move.w    trk_porttrgper(a5),d0    ;d0 = target period
  2009.         beq.s    fx_03rts
  2010.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  2011.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  2012.         cmp.w    d0,d1
  2013.         bhi.s    subper    ;curr. period > target period
  2014.         add.w    d4,d1    ;add the period
  2015.         cmp.w    d0,d1
  2016.         bge.s    targreached
  2017.         bra.s    targnreach
  2018. subper:        sub.w    d4,d1    ;subtract
  2019.         cmp.w    d0,d1    ;compare current period to target period
  2020.         bgt.s    targnreach
  2021. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  2022.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  2023. targnreach:    move.w    d1,trk_prevper(a5)
  2024. fx_03rts    rts
  2025. ;    **************************************** Effect 13 ******
  2026. fx_13:        cmp.b    #3,d3
  2027.         bge.s    fx_13rts    ;if counter < 3
  2028.         neg.w    d4
  2029.         move.w    d4,trk_vibradjust(a5)    ;subtract effect qual...
  2030. fx_13rts    rts
  2031. ;    *********************************************************
  2032. fx_0c:        tst.b    d3
  2033.         bne.s    fx_13rts
  2034. dvc_0        move.b    trk_prevvol(a5),d1
  2035.         rts
  2036. ;    **************************************** Effect 10 ******
  2037. fx_10:
  2038.     IFNE    MIDI
  2039.         tst.b    d3
  2040.         bne.s    fx_13rts
  2041.         move.w    d4,d0
  2042.         bra.w    _InitMIDIDump
  2043.     ENDC
  2044.     IFEQ    MIDI
  2045.         rts
  2046.     ENDC
  2047. ;    **************************************** Effect 18 ******
  2048. fx_18        cmp.b    d4,d3
  2049.         bne.s    fx_18rts
  2050.         clr.b    trk_prevvol(a5)
  2051. fx_18rts    rts
  2052. ;    **************************************** Effect 1F ******
  2053. fx_1f        move.b    d4,d1
  2054.         lsr.b    #4,d4        ;note delay
  2055.         beq.s    nonotedelay
  2056.         cmp.b    d4,d3        ;compare to counter
  2057.         blt.s    fx_18rts    ;tick not reached
  2058.         bne.s    nonotedelay
  2059.         bra    playfxnote    ;trigger note
  2060. nonotedelay    and.w    #$0f,d1        ;retrig?
  2061.         beq.s    fx_18rts
  2062.         moveq    #0,d0
  2063.         move.b    d3,d0
  2064.         divu    d1,d0
  2065.         swap    d0        ;get modulo of counter/tick
  2066.         tst.w    d0
  2067.         bne.s    fx_18rts
  2068.         bra    playfxnote    ;retrigger
  2069. ;    **************************************** Effect 0F ******
  2070. ;    see below...
  2071. ;    *********************************************************
  2072.  
  2073. ; *******************************************************************
  2074. ; UpdatePerVol:    Update audio registers (period & volume) after FX
  2075. ; *******************************************************************
  2076. ; args:        a6 = DB            d7 = channel #
  2077. ;        a5 = track data
  2078. ; scratches:    d0, d1, a0, d5
  2079. UpdatePerVol    move.w    trk_prevper(a5),d5
  2080.     IFNE    SYNTH
  2081.         move.l    trk_synthptr(a5),d0
  2082.         beq.s    plr_upv_nosynth
  2083.         move.l    a1,-(sp)
  2084.         bsr.w    synth_start
  2085.         move.l    (sp)+,a1
  2086.     ENDC
  2087. plr_upv_nosynth    add.w    trk_vibradjust(a5),d5
  2088.         sub.w    trk_arpadjust(a5),d5
  2089.         clr.l    trk_vibradjust(a5)    ;clr both adjusts
  2090.         movea.l    trk_audioaddr(a5),a0
  2091.         move.w    d5,ac_per(a0)        ;push period
  2092.         moveq    #0,d0
  2093.         move.b    trk_tempvol(a5),d0
  2094.         bpl.s    plr_upv_setvol
  2095.         move.b    trk_prevvol(a5),d0
  2096. plr_upv_setvol    st    trk_tempvol(a5)
  2097. ; -------- GetRelVol: Calculate track volume -----------------------------
  2098. ; track # = d7, note vol = d0, song = a4
  2099.     IFNE    RELVOL
  2100.         mulu    trk_trackvol(a5),d0    ;d0 = master v. * track v. * volume
  2101.         lsr.w    #8,d0
  2102.     ENDC
  2103.         move.b    d0,ac_vol+1(a0)
  2104.         rts
  2105.  
  2106. ; **** a separate routine for handling command 0F
  2107. fx_0f        cmp.b    #$f1,d4
  2108.         bne.s    no0ff1
  2109.         cmp.b    #3,d3
  2110.         beq.s    playfxnote
  2111.         rts
  2112. no0ff1:        cmp.b    #$f2,d4
  2113.         bne.s    no0ff2
  2114.         cmp.b    #3,d3
  2115.         beq.s    playfxnote
  2116.         rts
  2117. no0ff2:        cmp.b    #$f3,d4
  2118.         bne.s    no0ff3
  2119.         move.b    d3,d0
  2120.         beq.s    cF_rts
  2121.         and.b    #1,d0        ;is 2 or 4
  2122.         bne.s    cF_rts
  2123. playfxnote:    moveq    #0,d1
  2124.         move.b    trk_currnote(a5),d1    ;get note # of curr. note
  2125.         beq.s    cF_rts
  2126.         move.b    trk_noteoffcnt(a5),d0    ;get hold counter
  2127.         bmi.s    pfxn_nohold        ;no hold, or hold over
  2128.         add.b    d3,d0            ;increase by counter val
  2129.         bra.s    pfxn_hold
  2130. pfxn_nohold    move.b    trk_inithold(a5),d0    ;get initial hold
  2131.         bne.s    pfxn_hold
  2132.         st    d0
  2133. pfxn_hold    move.b    d0,trk_noteoffcnt(a5)
  2134.         movem.l    a1/a3/d3/d6,-(sp)
  2135.         moveq    #0,d3
  2136.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  2137.         movea.l    trk_previnstra(a5),a3
  2138.         bsr    _PlayNote
  2139. pndone_0ff    movem.l    (sp)+,a1/a3/d3/d6
  2140. cF_rts        rts
  2141. no0ff3:        cmp.b    #$f4,d4        ;triplet cmd 1
  2142.         bne.s    no0ff4
  2143.         moveq    #0,d0
  2144.         move.b    msng_tempo2(a4),d0
  2145.         divu    #3,d0
  2146.         cmp.b    d0,d3
  2147.         beq.s    playfxnote
  2148.         rts
  2149. no0ff4        cmp.b    #$f5,d4        ;triplet cmd 2
  2150.         bne.s    no0ff5
  2151.         moveq    #0,d0
  2152.         move.b    msng_tempo2(a4),d0
  2153.         divu    #3,d0
  2154.         add.w    d0,d0
  2155.         cmp.b    d0,d3
  2156.         beq.s    playfxnote
  2157.         rts
  2158. no0ff5        cmp.b    #$f8,d4        ;f8 = filter off
  2159.         beq.s    plr_filteroff
  2160.         cmp.b    #$f9,d4        ;f9 = filter on
  2161.         bne.s    cF_rts
  2162.         bclr    #1,$bfe001
  2163.         bset    #0,msng_flags(a4)
  2164.         rts
  2165. plr_filteroff:    bset    #1,$bfe001
  2166.         bclr    #0,msng_flags(a4)
  2167.         rts
  2168.  
  2169. ; -------- HANDLE DMA WAIT (PROCESSOR-INDEPENDENT) -----------------------
  2170. _Wait1line:    move.w    d0,-(sp)
  2171. wl0:        move.b    $dff007,d0
  2172. wl1:        cmp.b    $dff007,d0
  2173.         beq.s    wl1
  2174.         dbf    d1,wl0
  2175.         move.w    (sp)+,d0
  2176.         rts
  2177. pushnewvals:    movea.l    (a1)+,a5
  2178.         lsr.b    #1,d0
  2179.         bcc.s    rpnewv
  2180.         move.l    trk_sampleptr(a5),d1
  2181.         beq.s    rpnewv
  2182.         movea.l    trk_audioaddr(a5),a0
  2183.         move.l    d1,ac_ptr(a0)
  2184.         move.w    trk_samplelen(a5),ac_len(a0)
  2185. rpnewv:        rts
  2186.  
  2187. ; -------- AUDIO DMA ROUTINE ---------------------------------------------
  2188. _StartDMA:    ;This small routine turns on audio DMA
  2189.         move.w    dmaonmsk-DB(a6),d0    ;dmaonmsk contains the mask of
  2190.         beq.s    sdma_nodmaon    ;the channels that must be turned on
  2191.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  2192.         moveq    #80,d1
  2193. ; The following line makes the playroutine one scanline slower. If your
  2194. ; song works well without the following instruction, you can leave it out.
  2195.     IFNE    SYNTH
  2196.         add.w    d1,d1    ;sometimes double wait time is required
  2197.     ENDC
  2198.         bsr.s    _Wait1line
  2199.         move.w    d0,$dff096    ;do that!!!
  2200.         moveq    #80,d1
  2201.         bsr.s    _Wait1line
  2202.         lea    trackdataptrs-DB(a6),a1
  2203.         bsr.s    pushnewvals
  2204.         bsr.s    pushnewvals
  2205.         bsr.s    pushnewvals
  2206.     IFNE    MIDI
  2207.         bsr.s    pushnewvals
  2208.     ENDC
  2209.     IFEQ    MIDI
  2210.         bra.s    pushnewvals
  2211.     ENDC
  2212. sdma_nodmaon
  2213.     IFNE    MIDI
  2214.         lea    bytesinnotebuff-DB(a6),a0
  2215.         move.w    (a0)+,d0
  2216.         beq.s    rpnewv
  2217.         bra.w    _AddMIDId
  2218.     ENDC
  2219.         rts
  2220.  
  2221. _SetTempo:
  2222.     IFNE    CIAB
  2223.         move.l    _module-DB(a6),d1
  2224.         beq.s    ST_x
  2225.         move.l    d1,a0
  2226.         movea.l    mmd_songinfo(a0),a0
  2227.         btst    #5,msng_flags2(a0)
  2228.         bne.s    ST_bpm
  2229.         cmp.w    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  2230.         bhi.s    calctempo
  2231.         subq.b    #1,d0
  2232.         add.w    d0,d0
  2233.         move.w    sttempo+2(pc,d0.w),d1
  2234.         bra.s    pushtempo
  2235. calctempo:    move.l    timerdiv-DB(a6),d1
  2236.         divu    d0,d1
  2237. pushtempo:    movea.l    craddr+4-DB(a6),a0
  2238.         move.b    d1,(a0)        ;and set the CIA timer
  2239.         lsr.w    #8,d1
  2240.         movea.l    craddr+8-DB(a6),a0
  2241.         move.b    d1,(a0)
  2242.     ENDC
  2243. ST_x        rts ;   vv-- These values are the SoundTracker tempos (approx.)
  2244. sttempo:    dc.w    $0f00
  2245.     IFNE    CIAB
  2246.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  2247. ST_bpm        move.b    msng_flags2(a0),d1
  2248.         and.w    #$1F,d1
  2249.         addq.b    #1,d1
  2250.         mulu    d1,d0
  2251.         move.l    bpmdiv-DB(a6),d1
  2252.         divu    d0,d1
  2253.         bra.s    pushtempo
  2254.     ENDC
  2255.  
  2256.     IFNE    MIDI
  2257. MIDIFX        add.b    d0,d0    ;* 2
  2258.         move.w    midicmd_table(pc,d0.w),d0
  2259.         jmp    midifx(pc,d0.w)
  2260. midicmd_table    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  2261.         dc.w    mfx_05-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2262.         dc.w    mfx_0a-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_0d-midifx,mfx_0e-midifx
  2263.         dc.w    mfx_0f-midifx
  2264.         dc.w    mfx_10-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_13-midifx
  2265.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_17-midifx
  2266.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2267.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,fx_1f-midifx
  2268. midifx        
  2269. mfx_01        lea    prevmidipbend-DB(a6),a0
  2270.         moveq    #0,d1
  2271.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  2272.         add.b    d1,d1        ;UWORD index
  2273.         tst.b    d4        ;x100??
  2274.         beq.s    resetpbend
  2275.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  2276.         lsl.w    #3,d4        ;multiply bend value by 8
  2277.         add.w    d4,d0
  2278.         cmp.w    #$3fff,d0
  2279.         bls.s    bendpitch
  2280.         move.w    #$3fff,d0
  2281. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  2282.         lsr.b    #1,d1        ;back to UBYTE
  2283.         or.b    #$e0,d1
  2284.         lea    noteondata-DB(a6),a0
  2285.         move.b    d1,(a0)        ;midi command & channel
  2286.         move.b    d0,1(a0)    ;lower value
  2287.         and.b    #$7f,1(a0)    ;clear bit 7
  2288.         lsr.w    #7,d0
  2289.         and.b    #$7f,d0        ;clr bit 7
  2290.         move.b    d0,2(a0)    ;higher 7 bits
  2291.         moveq    #3,d0
  2292.         bra.w    _AddMIDId
  2293.  
  2294. mfx_02        lea    prevmidipbend-DB(a6),a0
  2295.         moveq    #0,d1
  2296.         move.b    trk_prevmidich(a5),d1
  2297.         add.b    d1,d1
  2298.         tst.b    d4
  2299.         beq.s    resetpbend    ;x200??
  2300.         move.w    0(a0,d1.w),d0
  2301.         lsl.w    #3,d4
  2302.         sub.w    d4,d0
  2303.         bpl.s    bendpitch    ;not under 0
  2304.         moveq    #0,d0
  2305.         bra.s    bendpitch
  2306. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  2307.         bne.s    mfx_rts
  2308.         move.w    #$2000,d0
  2309.         bra.s    bendpitch
  2310. mfx_rts        rts
  2311. mfx_13
  2312. mfx_03        tst.b    d3
  2313.         bne.s    mfx_rts
  2314.         lea    prevmidipbend-DB(a6),a0
  2315.         moveq    #0,d1
  2316.         move.b    trk_prevmidich(a5),d1
  2317.         add.b    d1,d1
  2318.         move.b    d4,d0
  2319.         add.b    #128,d0
  2320.         lsl.w    #6,d0
  2321.         bra.s    bendpitch
  2322.  
  2323. mfx_0d        tst.b    d3
  2324.         bne.s    mfx_rts
  2325.         lea    noteondata+1-DB(a6),a0    ;CHANNEL AFTERTOUCH
  2326.         move.b    d4,(a0)    ;value
  2327.         bmi.s    mfx_rts
  2328.         move.b    trk_prevmidich(a5),-(a0)
  2329.         or.b    #$d0,(a0)
  2330.         moveq    #2,d0
  2331.         bra.w    _AddMIDId
  2332.  
  2333. mfx_0a        tst.b    d3
  2334.         bne.s    mfx_rts
  2335.         lea    noteondata+2-DB(a6),a0    ;POLYPHONIC AFTERTOUCH
  2336.         and.b    #$7f,d4
  2337.         move.b    d4,(a0)
  2338.         move.b    trk_prevmidin(a5),-(a0)
  2339.         ble.s    mfx_rts
  2340.         move.b    trk_prevmidich(a5),-(a0)
  2341.         or.b    #$A0,(a0)
  2342.         moveq    #3,d0
  2343.         bra.w    _AddMIDId
  2344.  
  2345. mfx_17        moveq    #$07,d0        ;07 = VOLUME
  2346.         bra.s    pushctrldata
  2347.  
  2348. mfx_04        moveq    #$01,d0        ;01 = MODULATION WHEEL
  2349.         bra.s    pushctrldata
  2350.  
  2351. mfx_0e        moveq    #$0a,d0
  2352. pushctrldata    tst.b    d3        ;do it only once in a note
  2353.         bne.s    mfx_rts2    ;(when counter = 0)
  2354.         lea    noteondata+2-DB(a6),a0 ;push "control change" data,
  2355.         move.b    d4,(a0)        ;second databyte
  2356.         bmi.s    mfx_rts2    ;$0 - $7F only
  2357.         move.b    d0,-(a0)    ;1st databyte
  2358.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  2359.         or.b    #$b0,(a0)    ;command (B)
  2360.         moveq    #3,d0
  2361.         bra.w    _AddMIDId
  2362.  
  2363. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  2364.         move.b    trk_prevmidich(a5),d6
  2365.         lea    midicontrnum-DB(a6),a0
  2366.         adda.w    d6,a0
  2367.         move.b    d4,(a0)
  2368. mfx_rts2    rts
  2369.  
  2370. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  2371.         bne.s    nomffa
  2372.         moveq    #$40,d0
  2373.         moveq    #$7f,d4
  2374.         bra.s    pushctrldata
  2375. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  2376.         bne.w    fx_0f
  2377.         moveq    #$40,d0
  2378.         moveq    #$00,d4
  2379.         bra.s    pushctrldata
  2380.  
  2381. mfx_00        tst.b    d4
  2382.         beq.s    mfx_rts2
  2383.         and.b    #$7f,d4
  2384.         move.b    trk_prevmidich(a5),d6
  2385.         lea    midicontrnum-DB(a6),a0
  2386.         move.b    0(a0,d6.w),d0
  2387.         bra.s    pushctrldata
  2388.  
  2389. mfx_10        tst.b    d3
  2390.         bne.s    mfx_rts3
  2391.         move.w    d4,d0
  2392.         bra.w    _InitMIDIDump
  2393.  
  2394. _ResetMIDI:    movem.l    d2/a2/a6,-(sp)
  2395.         movea.l    4.w,a6        ;ExecBase
  2396.         jsr    -$78(a6)    ;Disable()
  2397.         lea    DB,a6
  2398. ; Clear preset memory
  2399.         lea    prevmidicpres-DB(a6),a0
  2400.         moveq    #7,d2
  2401. RM_loop0    clr.l    (a0)+    ;force presets to be set again
  2402.         dbf    d2,RM_loop0
  2403.         clr.b    lastcmdbyte
  2404. ; Reset pitchbenders & modulation wheels
  2405.         lea    midiresd-DB(a6),a2
  2406.         move.b    #$e0,(a2)
  2407.         move.b    #$b0,3(a2)
  2408.         moveq    #15,d2
  2409. respbendl:    movea.l    a2,a0
  2410.         moveq    #6,d0
  2411.         bsr.w    _AddMIDId
  2412.         addq.b    #1,(a2)
  2413.         addq.b    #1,3(a2)
  2414.         dbf    d2,respbendl
  2415.         lea    prevmidipbend-DB(a6),a2
  2416.         moveq    #15,d2
  2417. resprevpbends:    move.w    #$2000,(a2)+
  2418.         dbf    d2,resprevpbends
  2419. ; Clear dump variables
  2420.         clr.b    sysx-DB(a6)
  2421.         lea    dumpqueue-DB(a6),a0
  2422.         move.l    a0,dqreadptr-DB(a6)
  2423.         move.l    a0,dqwriteptr-DB(a6)
  2424.         clr.w    dqentries-DB(a6)
  2425. ; Enable & exit
  2426.         movea.l    4.w,a6
  2427.         jsr    -$7e(a6)    ;Enable()
  2428.         movem.l    (sp)+,d2/a2/a6
  2429.         rts
  2430.     ENDC
  2431.  
  2432. ; *************************************************************************
  2433. ; *************************************************************************
  2434. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2435. ; *************************************************************************
  2436. ; *************************************************************************
  2437.  
  2438.     IFEQ    EASY
  2439.         XDEF    _InitModule,_PlayModule
  2440.         XDEF    _InitPlayer,_RemPlayer,_StopPlayer
  2441.         XDEF    _ContModule
  2442.     ENDC
  2443.  
  2444. ; *************************************************************************
  2445. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  2446. ; *************************************************************************
  2447.  
  2448. _InitModule:    movem.l    a2-a3/d2,-(sp)
  2449.         move.l    a0,-(sp)
  2450.         beq    IM_exit            ;0 => xit
  2451.     IFNE    RELVOL
  2452.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  2453.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  2454.         ext.w    d0
  2455.         lea    trackdataptrs,a2
  2456.         cmp.b    #'2',3(a0)        ;MMD2?
  2457.         bne.s    IM_mmd01
  2458.         move.w    msng_numtracks(a1),d1
  2459.         subq.w    #1,d1
  2460.         movea.l    msng_trkvoltbl(a1),a1
  2461.         bra.s    IM_loop0
  2462. IM_mmd01    lea    msng_trkvol(a1),a1    ;a1 = trkvol
  2463.         moveq    #MAX_MMD1_TRACKS-1,d1
  2464. IM_loop0    move.b    (a1)+,d2    ;get vol...
  2465.         ext.w    d2
  2466.         move.l    (a2)+,a3    ;pointer to track data
  2467.         mulu    d0,d2        ;mastervol * trackvol
  2468.         lsr.w    #4,d2
  2469.         move.w    d2,trk_trackvol(a3)
  2470.         dbf    d1,IM_loop0
  2471.     ENDC
  2472.     IFNE    SYNTH
  2473.         lea    trackdataptrs,a2
  2474.         moveq    #3,d1
  2475. IM_loop1    move.l    (a2)+,a3
  2476.         clr.l    trk_synthptr(a3)
  2477.         clr.b    trk_synthtype(a3)
  2478.         dbf    d1,IM_loop1
  2479.     ENDC
  2480.         lea    holdvals,a2
  2481.         movea.l    a0,a3
  2482.         move.l    mmd_expdata(a0),d0    ;expdata...
  2483.     IFEQ    MIDI
  2484.         beq.s    IM_clrhlddec        ;none here
  2485.     ENDC
  2486.     IFNE    MIDI
  2487.         beq.w    IM_clrhlddec
  2488.     ENDC
  2489.         move.l    d0,a1
  2490.         move.l    4(a1),d0        ;exp_smp
  2491.     IFEQ    MIDI
  2492.         beq.s    IM_clrhlddec    ;again.. nothing
  2493.     ENDC
  2494.     IFNE    MIDI
  2495.         beq.w    IM_clrhlddec
  2496.     ENDC
  2497.         move.l    d0,a0        ;InstrExt...
  2498.         move.w    8(a1),d2    ;# of entries
  2499.     IFEQ    MIDI
  2500.         beq.s    IM_clrhlddec
  2501.     ENDC
  2502.     IFNE    MIDI
  2503.         beq.w    IM_clrhlddec
  2504.     ENDC
  2505.         subq.w    #1,d2        ;-1 (for dbf)
  2506.         move.w    10(a1),d0    ;entry size
  2507.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  2508.     IFNE    MIDI
  2509.         lea    4*63(a2),a1    ;pointer to ext_midipsets...
  2510.     ENDC
  2511. IM_loop2    clr.b    2*63(a2)        ;clear finetune
  2512.         cmp.w    #3,d0
  2513.         ble.s    IM_noftune
  2514.         move.b    3(a0),126(a2)    ;InstrExt.finetune -> finetune
  2515. IM_noftune    clr.b    3*63(a2)    ;clear flags
  2516.         cmp.w    #6,d0
  2517.         blt.s    IM_noflags
  2518.         move.b    5(a0),3*63(a2)    ;InstrExt.flags -> flags
  2519.         bra.s    IM_gotflags
  2520. IM_noflags    cmp.w    #1,inst_replen(a3)
  2521.         bls.s    IM_gotflags
  2522.         bset    #0,3*63(a2)
  2523. IM_gotflags    clr.b    6*63(a2)    ;Initally OUTPUT_STD
  2524.         cmp.w    #9,d0
  2525.         blt.s    IM_noopdev
  2526.         move.b    8(a0),6*63(a2)    ;get InstrExt.output_device
  2527.     IFNE    AURA
  2528.         cmp.b    #1,8(a0)    ;is it OUTPUT_AURA?
  2529.         bne.s    IM_noopdev
  2530. ; does no harm to call several times...
  2531.         jsr    _InitAura(pc)
  2532.     ENDC
  2533. IM_noopdev
  2534.     IFNE    MIDI
  2535.         cmp.w    #2,d0
  2536.         ble.s    IM_nsmnoff
  2537.         tst.b    2(a0)        ;suppress MIDI note off?
  2538.         beq.s    IM_nsmnoff
  2539.         bset    #7,inst_midich(a3)
  2540. IM_nsmnoff    move.b    inst_midipreset(a3),d1
  2541.         ext.w    d1
  2542.         move.w    d1,(a1)
  2543.         cmp.w    #8,d0
  2544.         ble.s    IM_nolongpset
  2545.         move.w    6(a0),(a1)    ;-> ext_midipsets
  2546.         btst    #1,5(a0)
  2547.         beq.s    IM_nolongpset
  2548.         bset    #6,inst_midich(a3)
  2549. IM_nolongpset    addq.l    #2,a1
  2550.     ENDC
  2551.         move.b    1(a0),63(a2)    ;InstrExt.decay -> decay
  2552.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  2553.         adda.w    d0,a0        ;ptr to next InstrExt
  2554.         addq.l    #8,a3        ;next instrument...
  2555.         dbf    d2,IM_loop2
  2556.         bra.s    IM_exit
  2557. IM_clrhlddec    move.w    #3*63-1,d0    ;no InstrExt => clear holdvals/decays
  2558. IM_loop3    clr.w    (a2)+        ;..and finetunes/flags/ext_psets
  2559.         dbf    d0,IM_loop3
  2560.         movea.l    (sp),a0
  2561. ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
  2562. ; -------- also copy inst_midipreset to ext_midipsets.
  2563.         movea.l    mmd_songinfo(a0),a3
  2564.         lea    flags,a2
  2565.     IFNE    MIDI
  2566.         lea    ext_midipsets,a1
  2567.     ENDC
  2568.         moveq    #62,d0
  2569. IM_loop4    cmp.w    #1,inst_replen(a3)
  2570.         bls.s    IM_noreptflg
  2571.         bset    #0,(a2)
  2572. IM_noreptflg    addq.l    #1,a2
  2573.     IFNE    MIDI
  2574.         move.b    inst_midipreset(a3),d1
  2575.         ext.w    d1
  2576.         move.w    d1,(a1)+
  2577.     ENDC
  2578.         addq.l    #8,a3        ;next inst
  2579.         dbf    d0,IM_loop4
  2580. IM_exit        addq.l    #4,sp
  2581.         movem.l    (sp)+,a2-a3/d2
  2582.         rts
  2583. ; *************************************************************************
  2584. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  2585. ; *************************************************************************
  2586. _InitPlayer:
  2587.     IFNE    MIDI
  2588.         bsr.w    _GetSerial
  2589.         tst.l    d0
  2590.         bne.s    IP_error
  2591.     ENDC
  2592.         bsr.w    _AudioInit
  2593.         tst.l    d0
  2594.         bne.s    IP_error
  2595.         rts
  2596. IP_error    bsr.s    _RemPlayer
  2597.         moveq    #-1,d0
  2598.         rts
  2599. ; *************************************************************************
  2600. ; RemPlayer() -- free interrupt, audio, serial port etc..
  2601. ; *************************************************************************
  2602. _RemPlayer:    move.b    _timeropen,d0
  2603.         beq.s    RP_notimer    ;timer is not ours
  2604.         bsr.s    _StopPlayer
  2605. RP_notimer:    bsr.w    _AudioRem
  2606.     IFNE    MIDI
  2607.         bra.w    _FreeSerial
  2608.     ELSEIF
  2609.         rts
  2610.     ENDC
  2611. ; *************************************************************************
  2612. ; StopPlayer() -- stop the music
  2613. ; *************************************************************************
  2614. _StopPlayer:    lea    DB,a1
  2615.         move.b    _timeropen-DB(a1),d0
  2616.         beq.s    SP_end        ;res. alloc fail.
  2617.     IFNE    CIAB
  2618.         movea.l    craddr-DB(a1),a0
  2619.         bclr    #0,(a0)        ;stop timer
  2620.     ENDC
  2621.     IFNE    AURA
  2622.         jsr    _RemAura(pc)
  2623.     ENDC
  2624.         move.l    _module-DB(a1),d0
  2625.         beq.s    SP_nomod
  2626.         move.l    d0,a0
  2627.         clr.w    mmd_pstate(a0)
  2628.         clr.l    _module-DB(a1)
  2629. SP_nomod
  2630.     IFNE    MIDI
  2631.         clr.b    lastcmdbyte-DB(a1)
  2632.     ENDC
  2633.         bra.w    SoundOff
  2634. SP_end        rts
  2635.  
  2636.  
  2637. _ContModule    tst.b    _timeropen
  2638.         beq.s    SP_end
  2639.         movea.l    craddr,a1
  2640.         bclr    #0,(a1)
  2641.         move.l    a0,-(sp)
  2642.         bsr.w    SoundOff
  2643.         move.l    (sp)+,a0
  2644.         moveq    #0,d0
  2645.         bra.s    contpoint
  2646. ; *************************************************************************
  2647. ; PlayModule(a0 = module)  -- initialize & play it!
  2648. ; *************************************************************************
  2649. _PlayModule:    st    d0
  2650. contpoint    movem.l    a0/d0,-(sp)
  2651.         bsr    _InitModule
  2652.         movem.l    (sp)+,a0/d0
  2653.         move.l    a6,-(sp)
  2654.         lea    DB,a6
  2655.         tst.b    _timeropen-DB(a6)
  2656.         beq    PM_end        ;resource allocation failure
  2657.         move.l    a0,d1
  2658.         beq    PM_end        ;module failure
  2659.     IFNE    CIAB
  2660.         movea.l    craddr-DB(a6),a1
  2661.         bclr    #0,(a1)        ;stop timer...
  2662.     ENDC
  2663.         clr.l    _module-DB(a6)
  2664.     IFNE    MIDI
  2665.         clr.b    lastcmdbyte-DB(a6)
  2666.     ENDC
  2667.         move.w    _modnum,d1
  2668.         beq.s    PM_modfound
  2669. PM_nextmod    tst.l    mmd_expdata(a0)
  2670.         beq.s    PM_modfound
  2671.         move.l    mmd_expdata(a0),a1
  2672.         tst.l    (a1)
  2673.         beq.s    PM_modfound        ;no more modules here!
  2674.         move.l    (a1),a0
  2675.         subq.w    #1,d1
  2676.         bgt.s    PM_nextmod
  2677. PM_modfound    cmp.b    #'T',3(a0)
  2678.         bne.s    PM_nomodT
  2679.         move.b    #'0',3(a0)    ;change MCNT to MCN0
  2680. PM_nomodT    movea.l    mmd_songinfo(a0),a1        ;song
  2681.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  2682.         btst    #0,msng_flags(a1)
  2683.         bne.s    PM_filon
  2684.         bset    #1,$bfe001
  2685.         bra.s    PM_filset
  2686. PM_filon    bclr    #1,$bfe001
  2687. PM_filset    tst.b    d0
  2688.         beq.s    PM_noclr
  2689.         clr.l    mmd_pline(a0)
  2690.         clr.l    rptline-DB(a6)
  2691.         clr.w    blkdelay-DB(a6)
  2692. ; ---------- Set 'pblock' and 'pseq' to correct values...
  2693. PM_noclr    cmp.b    #'2',3(a0)
  2694.         bne.s    PM_oldpbset
  2695.         move.w    mmd_psecnum(a0),d1
  2696.         move.l    a2,-(sp)        ;need extra register
  2697.         movea.l    msng_sections(a1),a2
  2698.         add.w    d1,d1
  2699.         move.w    0(a2,d1.w),d1        ;get sequence number
  2700.         add.w    d1,d1
  2701.         add.w    d1,d1
  2702.         move.w    d1,mmd_pseq(a0)
  2703.         movea.l    msng_pseqs(a1),a2
  2704.         movea.l    0(a2,d1.w),a2        ;PlaySeq...
  2705.         move.w    mmd_pseqnum(a0),d1
  2706.         add.w    d1,d1
  2707.         move.w    42(a2,d1.w),d1        ;and the correct block..
  2708.         move.l    (sp)+,a2
  2709.         bra.s    PM_setblk
  2710. PM_oldpbset    move.w    mmd_pseqnum(a0),d1
  2711.         add.w    #msng_playseq,d1
  2712.         move.b    0(a1,d1.w),d1        ;get first playseq entry
  2713.         ext.w    d1
  2714. PM_setblk    move.w    d1,mmd_pblock(a0)
  2715.         move.w    #-1,mmd_pstate(a0)
  2716.         move.l    a0,_module-DB(a6)
  2717.         btst    #5,msng_flags2(a1)    ;BPM?
  2718.         seq    bpmcounter-DB(a6)
  2719.     IFNE    CIAB
  2720.         move.w    msng_deftempo(a1),d0    ;get default tempo
  2721.         movea.l    craddr-DB(a6),a1
  2722.         bsr.w    _SetTempo    ;set default tempo
  2723.         bset    #0,(a1)        ;start timer => PLAY!!
  2724.     ENDC
  2725. PM_end        move.l    (sp)+,a6
  2726.         rts
  2727. ; *************************************************************************
  2728.  
  2729. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  2730.         lea    DB,a4
  2731.         moveq    #0,d2
  2732.         movea.l    4.w,a6
  2733. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  2734.     IFNE    AUDDEV
  2735.         moveq    #1,d2
  2736.         moveq    #-1,d0
  2737.         jsr    -$14a(a6)    ;AllocSignal()
  2738.         tst.b    d0
  2739.         bmi.w    initerr
  2740.         move.b    d0,sigbitnum-DB(a4)
  2741. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  2742.         lea    allocport-DB(a4),a1
  2743.         move.b    d0,15(a1)    ;set mp_SigBit
  2744.         move.l    a1,-(sp)
  2745.         suba.l    a1,a1
  2746.         jsr    -$126(a6)    ;FindTask(0)
  2747.         move.l    (sp)+,a1
  2748.         move.l    d0,16(a1)    ;set mp_SigTask
  2749.         lea    reqlist-DB(a4),a0
  2750.         move.l    a0,(a0)        ;NEWLIST begins...
  2751.         addq.l    #4,(a0)
  2752.         clr.l    4(a0)
  2753.         move.l    a0,8(a0)    ;NEWLIST ends...
  2754. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  2755.         moveq    #2,d2
  2756.         lea    allocreq-DB(a4),a1
  2757.         lea    audiodevname-DB(a4),a0
  2758.         moveq    #0,d0
  2759.         moveq    #0,d1
  2760.         movea.l    4.w,a6
  2761.         jsr    -$1bc(a6)    ;OpenDevice()
  2762.         tst.b    d0
  2763.         bne.w    initerr
  2764.         st    audiodevopen-DB(a4)
  2765. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open cia resource
  2766.         moveq    #3,d2
  2767.     ENDC
  2768.     IFNE    CIAB
  2769.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  2770.         beq.s    init_pal
  2771.         move.l    #474326,timerdiv-DB(a4) ;Assume that CIA freq is 715 909 Hz
  2772.         move.l    #3579545/2,bpmdiv-DB(a4)
  2773. init_pal    moveq    #0,d3
  2774.         lea    cianame-DB(a4),a1
  2775.         move.b    #'a',3(a1)
  2776. open_ciares    moveq    #0,d0
  2777.         movea.l    4.w,a6
  2778.         jsr    -$1f2(a6)    ;OpenResource()
  2779.         move.l    d0,_ciaresource
  2780.         beq.s    try_CIAB
  2781.         moveq    #4,d2
  2782.         move.l    d0,a6
  2783.         lea    timerinterrupt-DB(a4),a1
  2784.         moveq    #0,d0        ;Timer A
  2785.         jsr    -$6(a6)        ;AddICRVector()
  2786.         tst.l    d0
  2787.         beq.s    got_timer
  2788.         addq.l    #4,d3        ;add base addr index
  2789.         lea    timerinterrupt-DB(a4),a1
  2790.         moveq    #1,d0        ;Timer B
  2791.         jsr    -$6(a6)        ;AddICRVector()
  2792.         tst.l    d0
  2793.         beq.s    got_timer
  2794. try_CIAB    lea    cianame-DB(a4),a1
  2795.         cmp.b    #'a',3(a1)
  2796.         bne.s    initerr
  2797.         addq.b    #1,3(a1)
  2798.         moveq    #8,d3        ;CIAB base addr index = 8
  2799.         bra.w    open_ciares
  2800. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  2801. got_timer    lea    craddr+8-DB(a4),a6
  2802.         move.l    cia_addr(pc,d3.w),d0
  2803.         move.l    d0,(a6)
  2804.         sub.w    #$100,d0
  2805.         move.l    d0,-(a6)
  2806.         moveq    #2,d3        ;assume timer B
  2807.         btst    #9,d0        ;timer A or B ?
  2808.         bne.s    got_timerB
  2809.         subq.b    #1,d3        ;not timer B -> subtract 1
  2810.         add.w    #$100,d0    ;calc offset to timer control reg
  2811. got_timerB    add.w    #$900,d0
  2812.         move.l    d0,-(a6)
  2813.         move.l    d0,a0            ;get Control Register
  2814.         and.b    #%10000000,(a0)        ;clear CtrlReg bits 0 - 6
  2815.         move.b    d3,_timeropen-DB(a4)    ;d3: 1 = TimerA 2 = TimerB
  2816.     ENDC
  2817.     IFNE    VBLANK
  2818.         moveq    #5,d0        ;INTB_VERTB
  2819.         lea    timerinterrupt-DB(a4),a1
  2820.         jsr    -$a8(a6)    ;AddIntServer
  2821.         st    _timeropen-DB(a4)
  2822.     ENDC
  2823.         moveq    #0,d0
  2824. initret:    movem.l    (sp)+,a4/a6/d2-d3
  2825.         rts
  2826. initerr:    move.l    d2,d0
  2827.         bra.s    initret
  2828.  
  2829. cia_addr:    dc.l    $BFE501,$BFE701,$BFD500,$BFD700
  2830.  
  2831. _AudioRem:    movem.l    a5-a6,-(sp)
  2832.         lea    DB,a5
  2833.         moveq    #0,d0
  2834.         move.b    _timeropen,d0
  2835.         beq.s    rem1
  2836. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  2837.         clr.b    _timeropen
  2838.     IFNE    CIAB
  2839.         move.l    _ciaresource,a6
  2840.         lea    timerinterrupt-DB(a5),a1
  2841.         subq.b    #1,d0
  2842.         jsr    -$c(a6)        ;RemICRVector
  2843.     ENDC
  2844.     IFNE    VBLANK
  2845.         movea.l    4.w,a6
  2846.         lea    timerinterrupt(pc),a1
  2847.         moveq    #5,d0
  2848.         jsr    -$ae(a6)    ;RemIntServer
  2849.     ENDC
  2850. rem1:
  2851.     IFNE    AUDDEV
  2852.         movea.l    4.w,a6
  2853.         tst.b    audiodevopen-DB(a5)
  2854.         beq.s    rem2
  2855.         move.w    #$000f,$dff096    ;stop audio DMA
  2856. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  2857.         lea    allocreq-DB(a5),a1
  2858.         jsr    -$1c2(a6)    ;CloseDevice()
  2859.         clr.b    audiodevopen-DB(a5)
  2860. rem2:        moveq    #0,d0
  2861.         move.b    sigbitnum-DB(a5),d0
  2862.         bmi.s    rem3
  2863. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  2864.         jsr    -$150(a6)    ;FreeSignal()
  2865.         st    sigbitnum-DB(a5)
  2866. rem3:
  2867.     ENDC
  2868.         movem.l    (sp)+,a5-a6
  2869.         rts
  2870.  
  2871.     IFNE    MIDI
  2872. _GetSerial:    movem.l    a5-a6,-(sp)    ;Get serial port for MIDI
  2873.         lea    DB,a5
  2874.         bsr.s    GetSer2
  2875.         tst.l    d0        ;got the port??
  2876.         beq.s    rgser        ;yes
  2877.         movea.l    4.w,a6        ;no..try to flush serial.device:
  2878.         jsr    -$84(a6)        ;Forbid
  2879.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  2880.         lea    serdev-DB(a5),a1    ;"serial.device"
  2881.         jsr    -$114(a6)        ;FindName
  2882.         tst.l    d0
  2883.         beq.s    serdnotf        ;no serial.device!!
  2884.         move.l    d0,a1
  2885.         jsr    -$1b6(a6)        ;RemDevice
  2886. serdnotf:    jsr    -$8a(a6)        ;and Permit
  2887.         bsr.s    GetSer2        ;now try it again...
  2888. rgser:        movem.l    (sp)+,a5-a6
  2889.         rts
  2890.  
  2891. GetSer2:    movea.l    4.w,a6
  2892.         moveq    #0,d0
  2893.         lea    miscresname-DB(a5),a1
  2894.         jsr    -$1f2(a6)    ;OpenResource()
  2895.         move.l    d0,miscresbase-DB(a5)
  2896.         tst.l    d0
  2897.         beq.s    gserror
  2898.         move.l    d0,a6
  2899.         lea    medname-DB(a5),a1
  2900.         moveq    #0,d0        ;serial port
  2901.         jsr    -$6(a6)        ;AllocMiscResource()
  2902.         tst.l    d0
  2903.         bne.s    gserror
  2904.         lea    medname-DB(a5),a1
  2905.         moveq    #1,d0        ;serial bits
  2906.         jsr    -$6(a6)
  2907.         tst.l    d0
  2908.         beq.s    gs2_allocok
  2909.         moveq    #0,d0
  2910.         jsr    -$c(a6)        ;bits failed -> Free serial port
  2911.         bra.s    gserror
  2912. gs2_allocok    move.w    $dff01c,d0
  2913.         btst    #0,d0
  2914.         sne    intrson-DB(a5)
  2915.         moveq    #0,d0        ;TBE
  2916.         lea    serinterrupt-DB(a5),a1
  2917.         move.l    4.w,a6
  2918.         jsr    -$a2(a6)    ;SetIntVector()
  2919.         move.l    d0,prevtbe-DB(a5)
  2920.         move.w    #$8001,$dff09a    ;TBE on
  2921.         move.w    #114,$dff032    ;set baud rate (SERPER)
  2922.         st    serportalloc-DB(a5)
  2923.         moveq    #0,d0
  2924.         rts
  2925. gserror:    moveq    #-1,d0
  2926.         rts
  2927.  
  2928. _FreeSerial:    movem.l    a5-a6,-(sp)
  2929.         lea    DB,a5
  2930.         tst.l    miscresbase-DB(a5)
  2931.         beq.s    retfs
  2932.         tst.b    serportalloc-DB(a5)
  2933.         beq.s    retfs
  2934. wmb_loop    move.w    $dff018,d0    ;WAIT until all data sent
  2935.         btst    #12,d0        ;test TSRE bit of SERDAT
  2936.         beq.s    wmb_loop
  2937.         move.w    #$0001,$dff09a    ;disable TBE
  2938.         movea.l    4.w,a6
  2939.         move.l    prevtbe-DB(a5),a1
  2940.         moveq    #0,d0
  2941.         jsr    -$a2(a6)    ;SetIntVector()
  2942. fs_noptbe    movea.l    miscresbase-DB(a5),a6
  2943.         moveq    #0,d0        ;serial port
  2944.         jsr    -$c(a6)        ;FreeMiscResource()
  2945.         moveq    #1,d0        ;serial bits
  2946.         jsr    -$c(a6)
  2947.         clr.b    serportalloc-DB(a5)
  2948.         clr.b    lastcmdbyte-DB(a5)
  2949. retfs:        movem.l    (sp)+,a5-a6
  2950.         rts
  2951.  
  2952. ; Message number in d0.
  2953. _InitMIDIDump:    tst.b    serportalloc
  2954.         beq.s    idd_rts
  2955.         movem.l    a1/a5/a6,-(sp)    ;a1 = data pointer, d1 = length
  2956.         lea    DB,a5
  2957.         movea.l    4.w,a6            ;ExecBase
  2958.         jsr    -$78(a6)        ;Disable()
  2959.         cmp.w    #16,dqentries-DB(a5)    ;dump queue full?
  2960.         bge.s    idd_exit        ;exit without doing anything
  2961.         lea    dqwriteptr-DB(a5),a1
  2962.         movea.l    (a1),a0
  2963.         move.w    d0,(a0)+        ;store message number
  2964.         cmpa.l    a1,a0            ;queue end?
  2965.         bne.s    idd_noresetbuff
  2966.         lea    dumpqueue-DB(a5),a0    ;reset write pointer
  2967. idd_noresetbuff    move.l    a0,(a1)            ;and write it back.
  2968.         addq.w    #1,dqentries-DB(a5)
  2969.         tst.b    sysx-DB(a5)        ;already sending data?
  2970.         bne.s    idd_exit        ;yes. Don't initiate new send.
  2971.         clr.b    lastcmdbyte-DB(a5)
  2972.         bsr    StartNewDump
  2973.         move.w    $dff018,d0        ;SERDATR
  2974.         btst    #13,d0
  2975.         beq.s    idd_exit
  2976.         move.w    #$8001,$dff09c        ;request TBE
  2977. idd_exit    jsr    -$7e(a6)        ;Enable()
  2978.         movem.l    (sp)+,a1/a5/a6
  2979. idd_rts        rts
  2980.  
  2981. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable..(Interrupts are enabled anyway)
  2982.         move.w    #1,$9c(a0)            ;clear intreq bit
  2983.         tst.b    sysx-buffptr(a1)        ;sysx??
  2984.         bne.s    sih_sysx
  2985.         move.w    bytesinbuff-buffptr(a1),d0    ;bytesinbuff
  2986.         beq.s    exsih                ;buffer empty
  2987.         movea.l    readbuffptr-buffptr(a1),a5    ;get buffer read pointer
  2988.         move.w    #$100,d1            ;Stop bit
  2989.         move.b    (a5)+,d1            ;get byte
  2990.         move.w    d1,$30(a0)            ;and push it to SERDAT
  2991.         cmpa.l    a1,a5                ;shall we reset ptr?
  2992.         bne.s    norrbuffptr            ;not yet..
  2993.         lea    -256(a1),a5
  2994. norrbuffptr    subq.w    #1,d0                ;one less bytes in buffer
  2995.         move.w    d0,bytesinbuff-buffptr(a1)    ;remember it
  2996.         move.l    a5,readbuffptr-buffptr(a1)    ;push new read ptr back
  2997. exsih        move.w    #$c000,$9a(a0)
  2998.         rts
  2999. sih_sysx    move.w    #$100,d1
  3000.         movea.l    sysxptr-buffptr(a1),a5    ;data pointer
  3001.         move.b    (a5)+,d1
  3002.         move.l    a5,sysxptr-buffptr(a1)
  3003.         move.w    d1,$30(a0)        ;-> SERDAT
  3004.         subq.l    #1,sysxleft-buffptr(a1)    ;sub data left length
  3005.         bne.s    exsih        ;not 0w
  3006.         lea    DB,a5
  3007.         clr.b    lastcmdbyte-DB(a5)
  3008.         bsr.s    StartNewDump
  3009.         bra.s    exsih
  3010.  
  3011. StartNewDump:    tst.w    dqentries-DB(a5)    ;queue empty?
  3012.         beq.s    snd_exit2
  3013.         movea.l    dqreadptr-DB(a5),a1    ;get read pointer
  3014.         move.w    (a1)+,d0        ;get message number (D0)
  3015.         cmpa.l    #dqwriteptr,a1        ;queue end?
  3016.         bne.s    snd_noresetbuff
  3017.         lea    dumpqueue-DB(a5),a1    ;reset write pointer
  3018. snd_noresetbuff    move.l    a1,dqreadptr-DB(a5)    ;and write it back.
  3019.         subq.w    #1,dqentries-DB(a5)
  3020. ; then attempt to search the given message (# in D0)
  3021.         move.l    _module-DB(a5),d1
  3022.         beq.s    StartNewDump
  3023.         move.l    d1,a1
  3024.         move.l    mmd_expdata(a1),d1
  3025.         beq.s    StartNewDump
  3026.         move.l    d1,a1
  3027.         move.l    52(a1),d1        ;exp_dump
  3028.         beq.s    StartNewDump
  3029.         move.l    d1,a1
  3030.         cmp.w    (a1),d0
  3031.         bge.s    StartNewDump
  3032.         addq.l    #8,a1            ;points to MMDDump ptr table
  3033.         add.w    d0,d0
  3034.         add.w    d0,d0            ;number *= 4
  3035.         adda.w    d0,a1
  3036.         movea.l    (a1),a1
  3037. ; initialize send variables (msg addr. in A0)
  3038. snd_found    move.l    (a1)+,sysxleft-DB(a5)    ;length
  3039.         move.l    (a1),sysxptr-DB(a5)    ;data pointer
  3040.         st    sysx-DB(a5)
  3041.         rts
  3042. snd_exit2    clr.b    sysx-DB(a5)        ;finish dump
  3043.         rts
  3044.  
  3045. _AddMIDIData    move.l    a6,-(sp)
  3046.         lea    DB,a6
  3047.         bsr.s    _AddMIDId
  3048.         move.l    (sp)+,a6
  3049.         rts
  3050.  
  3051. _AddMIDId    movem.l    a1-a3/a5,-(sp)
  3052.         tst.b    serportalloc-DB(a6)
  3053.         beq.s    retamd1
  3054.         movea.l    4.w,a5
  3055.         lea    $dff09a,a3
  3056.         move.w    #$4000,(a3)    ;Disable interrupts
  3057.         addq.b    #1,$126(a5)    ;ExecBase->IDNestCnt
  3058.         lea    buffptr-DB(a6),a2    ;end of buffer (ptr)
  3059.         move.w    -130(a3),d1    ;-130(a3) = $dff018 (SERDATR)
  3060.         btst    #13,d1
  3061.         beq.s    noTBEreq
  3062.         move.w    #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  3063. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  3064.         subq.w    #1,d0        ;-1 for DBF
  3065. adddataloop    move.b    (a0)+,d1    ;get byte
  3066.         bpl.s    norscheck    ;this isn't a status byte
  3067.         cmp.b    #$ef,d1        ;ignore system messages
  3068.         bhi.s    norscheck
  3069.         cmp.b    lastcmdbyte-DB(a6),d1    ;same as previous status byte?
  3070.         beq.s    samesb            ;yes, skip
  3071.         move.b    d1,lastcmdbyte-DB(a6)    ;no, don't skip but store.
  3072. norscheck    move.b    d1,(a1)+        ;push to midi send buffer
  3073.         addq.w    #1,8(a2)
  3074. samesb        cmpa.l    a2,a1            ;end of buffer??
  3075.         bne.s    noresbuffptr        ;no.
  3076.         lea    sendbuffer-DB(a6),a1    ;reset
  3077. noresbuffptr    dbf    d0,adddataloop
  3078.         move.l    a1,(a2)            ;push back new buffer ptr
  3079.         subq.b    #1,$126(a5)
  3080.         bge.s    retamd1
  3081.         move.w    #$c000,(a3)    ;enable interrupts again
  3082. retamd1        movem.l    (sp)+,a1-a3/a5
  3083.         rts
  3084.     ENDC
  3085.  
  3086.         DATA
  3087. DB:        ;Data base pointer
  3088.     IFNE    MIDI
  3089. sendbuffer    ds.b    256
  3090. buffptr        dc.l    sendbuffer
  3091. readbuffptr    dc.l    sendbuffer
  3092. bytesinbuff    dc.w    0
  3093. sysx        dc.b    0
  3094. lastcmdbyte    dc.b    0
  3095. sysxptr        dc.l    0
  3096. sysxleft    dc.l    0
  3097. dumpqueue    ds.w    16
  3098. dqwriteptr    dc.l    dumpqueue
  3099. dqreadptr    dc.l    dumpqueue
  3100. dqentries    dc.w    0
  3101.     ENDC
  3102. miscresbase    dc.l    0
  3103. timerdiv    dc.l    470000
  3104.     IFNE    AUDDEV
  3105. audiodevopen    dc.b    0
  3106. sigbitnum    dc.b    -1
  3107.     ENDC
  3108.     IFNE    MIDI
  3109. serportalloc    dc.b    0
  3110.     ENDC
  3111.         even
  3112.     IFNE    MIDI
  3113. preschgdata    dc.l    0
  3114. noteondata    dc.l    0
  3115.     ENDC
  3116. _module        dc.l    0
  3117. dmaonmsk    dc.w    0 ;\_May not be
  3118.     IFNE    MIDI
  3119. bytesinnotebuff    dc.w    0 ;/ separated!
  3120. noteonbuff    ds.b    (MAX_NUMTRACKS+2)*3
  3121.         even
  3122. intrson        dc.b    0,0
  3123. prevtbe        dc.l    0
  3124.     ENDC
  3125.     IFNE    CIAB
  3126. _ciaresource    dc.l    0
  3127. craddr        dc.l    0
  3128.         dc.l    0    ;tloaddr
  3129.         dc.l    0    ;thiaddr
  3130.     ENDC
  3131. timerinterrupt    dc.w    0,0,0,0,0
  3132.         dc.l    timerintname,DB
  3133.         dc.l    _IntHandler
  3134.     IFNE    MIDI
  3135. serinterrupt    dc.w    0,0,0,0,0
  3136.         dc.l    serintname,buffptr,SerIntHandler
  3137.     ENDC
  3138.     IFNE    AUDDEV
  3139. allocport    dc.l    0,0    ;succ, pred
  3140.         dc.b    4,0    ;NT_MSGPORT
  3141.         dc.l    0    ;name
  3142.         dc.b    0,0    ;flags = PA_SIGNAL
  3143.         dc.l    0    ;task
  3144. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  3145.         dc.b    5,0
  3146. allocreq    dc.l    0,0
  3147.         dc.b    0,127    ;NT_UNKNOWN, use maximum priority (127)
  3148.         dc.l    0,allocport    ;name, replyport
  3149.         dc.w    68        ;length
  3150.         dc.l    0    ;io_Device
  3151.         dc.l    0    ;io_Unit
  3152.         dc.w    0    ;io_Command
  3153.         dc.b    0,0    ;io_Flags, io_Error
  3154.         dc.w    0    ;ioa_AllocKey
  3155.         dc.l    sttempo    ;ioa_Data
  3156.         dc.l    1    ;ioa_Length
  3157.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  3158.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  3159. audiodevname    dc.b    'audio.device',0
  3160.     ENDC
  3161.     IFNE    CIAB
  3162. cianame        dc.b    'ciax.resource',0
  3163. _timeropen    dc.b    0
  3164.     ENDC
  3165. timerintname    dc.b    'OMEDTimerInterrupt',0
  3166.     IFNE    MIDI
  3167. serintname    dc.b    'OMEDSerialInterrupt',0
  3168. miscresname    dc.b    'misc.resource',0
  3169. serdev        dc.b    'serial.device',0
  3170. medname        dc.b    'OctaMED Pro modplayer',0
  3171.     ENDC
  3172.         even
  3173.     IFNE    MIDI
  3174. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  3175.  
  3176. midicontrnum    ds.b    16
  3177.  
  3178. prevmidicpres    dc.l    0,0,0,0,0,0,0,0 ; 16 * 2 bytes
  3179.  
  3180. prevmidipbend    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3181.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3182.     ENDC
  3183. ; TRACK-data structures (see definitions at the end of this file)
  3184. t03d        ds.b    TAAOFFS
  3185.         dc.l    $dff0a0
  3186.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3187.         dc.b    $ff
  3188. t03de        ds.b    T03SZ-(t03de-t03d)
  3189.         ds.b    TAAOFFS
  3190.         dc.l    $dff0b0
  3191.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3192.         dc.b    $ff
  3193.         ds.b    T03SZ-(t03de-t03d)
  3194.         ds.b    TAAOFFS
  3195.         dc.l    $dff0c0
  3196.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3197.         dc.b    $ff
  3198.         ds.b    T03SZ-(t03de-t03d)
  3199.         ds.b    TAAOFFS
  3200.         dc.l    $dff0d0
  3201.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3202.         dc.b    $ff
  3203.         ds.b    T03SZ-(t03de-t03d)
  3204. t463d        ds.b    (MAX_NUMTRACKS-4)*T415SZ
  3205. trackdataptrs    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  3206. ; Build pointer table. This works on Devpac assembler, other assemblers
  3207. ; may need modifications.
  3208. TRKCOUNT    SET    0
  3209.         REPT    (MAX_NUMTRACKS-4)
  3210.         dc.l    t463d+TRKCOUNT
  3211. TRKCOUNT    SET    TRKCOUNT+T415SZ
  3212.         ENDR
  3213.  
  3214. nextblock    dc.b    0 ;\ DON'T SEPARATE
  3215. nxtnoclrln    dc.b    0 :/
  3216. numtracks    dc.w    0 ;\ DON'T SEPARATE
  3217. numlines    dc.w    0 ;/
  3218. numpages    dc.w    0
  3219. nextblockline    dc.w    0
  3220. rptline        dc.w    0 ;\ DON'T SEPARATE
  3221. rptcounter    dc.w    0 ;/
  3222. blkdelay    dc.w    0    ;block delay (PT PatternDelay)
  3223. bpmcounter    dc.w    0
  3224. bpmdiv        dc.l    3546895/2
  3225. fxplineblk    dc.l    0    ;for reading effects
  3226.  
  3227. ; Fields in struct InstrExt (easier to access this way rather than
  3228. ; searching through the module).
  3229. holdvals    ds.b 63
  3230. decays        ds.b 63
  3231. finetunes    ds.b 63
  3232. flags        ds.b 63
  3233. ext_midipsets    ds.w 63
  3234. outputdevs    ds.b 63
  3235. playing_aura    ds.b 1
  3236.         EVEN
  3237.  
  3238. ; Below are the period tables. There's one table for each finetune position.
  3239.     IFNE    SYNTH|IFFMOCT
  3240.     dc.w    3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812
  3241.     dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
  3242.     ENDC
  3243. per0    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  3244.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  3245.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3246.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3247.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3248.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3249.     IFNE    SYNTH|IFFMOCT
  3250.     dc.w    3400,3209,3029,2859,2699,2547,2404,2269,2142,2022,1908,1801
  3251.     dc.w    1700,1605,1515,1430,1349,1274,1202,1135,1071,1011,954,901
  3252.     ENDC
  3253. per1    dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  3254.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  3255.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3256.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3257.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3258.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3259.     IFNE    SYNTH|IFFMOCT
  3260.     dc.w    3376,3187,3008,2839,2680,2529,2387,2253,2127,2007,1895,1788
  3261.     dc.w    1688,1593,1504,1419,1340,1265,1194,1127,1063,1004,947,894
  3262.     ENDC
  3263. per2    dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  3264.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  3265.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3266.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3267.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3268.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3269.     IFNE    SYNTH|IFFMOCT
  3270.     dc.w    3352,3164,2986,2819,2660,2511,2370,2237,2112,1993,1881,1776
  3271.     dc.w    1676,1582,1493,1409,1330,1256,1185,1119,1056,997,941,888
  3272.     ENDC
  3273. per3    dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  3274.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  3275.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3276.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3277.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3278.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3279.     IFNE    SYNTH|IFFMOCT
  3280.     dc.w    3328,3141,2965,2799,2641,2493,2353,2221,2097,1979,1868,1763
  3281.     dc.w    1664,1571,1482,1399,1321,1247,1177,1111,1048,989,934,881
  3282.     ENDC
  3283. per4    dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  3284.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  3285.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3286.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3287.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3288.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3289.     IFNE    SYNTH|IFFMOCT
  3290.     dc.w    3304,3119,2944,2778,2622,2475,2336,2205,2081,1965,1854,1750
  3291.     dc.w    1652,1559,1472,1389,1311,1238,1168,1103,1041,982,927,875
  3292.     ENDC
  3293. per5    dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  3294.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  3295.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3296.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3297.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3298.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3299.     IFNE    SYNTH|IFFMOCT
  3300.     dc.w    3280,3096,2922,2758,2603,2457,2319,2189,2066,1950,1841,1738
  3301.     dc.w    1640,1548,1461,1379,1302,1229,1160,1095,1033,975,920,869
  3302.     ENDC
  3303. per6    dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  3304.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  3305.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3306.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3307.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3308.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3309.     IFNE    SYNTH|IFFMOCT
  3310.     dc.w    3256,3073,2901,2738,2584,2439,2302,2173,2051,1936,1827,1725
  3311.     dc.w    1628,1537,1450,1369,1292,1220,1151,1087,1026,968,914,862
  3312.     ENDC
  3313. per7    dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  3314.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  3315.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3316.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3317.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3318.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3319.     IFNE    SYNTH|IFFMOCT
  3320.     dc.w    3628,3424,3232,3051,2880,2718,2565,2421,2285,2157,2036,1922
  3321.     dc.w    1814,1712,1616,1525,1440,1359,1283,1211,1143,1079,1018,961
  3322.     ENDC
  3323. per_8    dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  3324.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  3325.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3326.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3327.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3328.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3329.     IFNE    SYNTH|IFFMOCT
  3330.     dc.w    3588,3387,3197,3017,2848,2688,2537,2395,2260,2133,2014,1901
  3331.     dc.w    1794,1693,1598,1509,1424,1344,1269,1197,1130,1067,1007,950
  3332.     ENDC
  3333. per_7    dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  3334.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  3335.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3336.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3337.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3338.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3339.     IFNE    SYNTH|IFFMOCT
  3340.     dc.w    3576,3375,3186,3007,2838,2679,2529,2387,2253,2126,2007,1894
  3341.     dc.w    1788,1688,1593,1504,1419,1339,1264,1193,1126,1063,1003,947
  3342.     ENDC
  3343. per_6    dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  3344.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  3345.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3346.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3347.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3348.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3349.     IFNE    SYNTH|IFFMOCT
  3350.     dc.w    3548,3349,3161,2984,2816,2658,2509,2368,2235,2110,1991,1879
  3351.     dc.w    1774,1674,1580,1492,1408,1329,1254,1184,1118,1055,996,940
  3352.     ENDC
  3353. per_5    dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  3354.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  3355.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3356.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3357.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3358.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3359.     IFNE    SYNTH|IFFMOCT
  3360.     dc.w    3524,3326,3140,2963,2797,2640,2492,2352,2220,2095,1978,1867
  3361.     dc.w    1762,1663,1570,1482,1399,1320,1246,1176,1110,1048,989,933
  3362.     ENDC
  3363. per_4    dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  3364.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  3365.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3366.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3367.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3368.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3369.     IFNE    SYNTH|IFFMOCT
  3370.     dc.w    3500,3304,3118,2943,2778,2622,2475,2336,2205,2081,1964,1854
  3371.     dc.w    1750,1652,1559,1472,1389,1311,1237,1168,1102,1041,982,927
  3372.     ENDC
  3373. per_3    dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  3374.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  3375.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3376.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3377.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3378.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3379.     IFNE    SYNTH|IFFMOCT
  3380.     dc.w    3472,3277,3093,2920,2756,2601,2455,2317,2187,2064,1949,1839
  3381.     dc.w    1736,1639,1547,1460,1378,1301,1228,1159,1094,1032,974,920
  3382.     ENDC
  3383. per_2    dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  3384.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  3385.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3386.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3387.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3388.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3389.     IFNE    SYNTH|IFFMOCT
  3390.     dc.w    3448,3254,3072,2899,2737,2583,2438,2301,2172,2050,1935,1827
  3391.     dc.w    1724,1627,1536,1450,1368,1292,1219,1151,1086,1025,968,913
  3392.     ENDC
  3393. per_1    dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  3394.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  3395.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3396.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3397.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3398.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3399.  
  3400. _periodtable
  3401.     dc.l    per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
  3402.     dc.l    per1,per2,per3,per4,per5,per6,per7
  3403.  
  3404.     IFND    __G2
  3405.         section "datachip",data,chip ;for A68k
  3406.     ENDC
  3407.     IFD    __G2
  3408.         section "datachip",data_c ;this is for Devpac 2
  3409.     ENDC
  3410.         XDEF    _modnum
  3411.     IFNE    EASY
  3412. easymod        INCBIN    "module"    ;<<<<< MODULE NAME HERE!
  3413.     ENDC
  3414. _chipzero    dc.l    0
  3415. _modnum        dc.w    0    ;number of module to play
  3416.  
  3417. ; macros for entering offsets
  3418. DEFWORD    MACRO
  3419. \1    EQU    OFFS
  3420. OFFS    SET    OFFS+2
  3421.     ENDM
  3422. DEFBYTE    MACRO
  3423. \1    EQU    OFFS
  3424. OFFS    SET    OFFS+1
  3425.     ENDM
  3426. DEFLONG    MACRO
  3427. \1    EQU    OFFS
  3428. OFFS    SET    OFFS+4
  3429.     ENDM
  3430.  
  3431. OFFS    SET    0
  3432. ; the track-data structure definition:
  3433.     DEFBYTE    trk_prevnote    ;previous note number (0 = none, 1 = C-1..)
  3434.     DEFBYTE    trk_previnstr    ;previous instrument number
  3435.     DEFBYTE    trk_prevvol    ;previous volume
  3436.     DEFBYTE    trk_prevmidich    ;previous MIDI channel
  3437.     DEFBYTE    trk_prevmidin    ;previous MIDI note
  3438.     DEFBYTE    trk_noteoffcnt    ;note-off counter (hold)
  3439.     DEFBYTE    trk_inithold    ;default hold for this instrument
  3440.     DEFBYTE    trk_initdecay    ;default decay for....
  3441.     DEFBYTE    trk_stransp    ;instrument transpose
  3442.     DEFBYTE    trk_finetune    ;finetune
  3443.     DEFWORD    trk_soffset    ;new sample offset | don't sep this and 2 below!
  3444.     DEFBYTE    trk_miscflags    ;bit: 7 = cmd 3 exists, 0 = cmd E exists
  3445.     DEFBYTE    trk_currnote    ;note on CURRENT line (0 = none, 1 = C-1...)
  3446.     DEFBYTE    trk_outputdev    ;output device
  3447.     DEFBYTE    trk_fxtype    ;fx type: 0 = norm, 1 = none, -1 = MIDI
  3448.     DEFLONG    trk_previnstra    ;address of the previous instrument data
  3449.     DEFWORD    trk_trackvol
  3450. ; the following data only on tracks 0 - 3
  3451.     DEFWORD    trk_prevper    ;previous period
  3452.     DEFLONG    trk_audioaddr    ;hardware audio channel base address
  3453.     DEFLONG    trk_sampleptr    ;pointer to sample
  3454.     DEFWORD    trk_samplelen    ;length (>> 1)
  3455.     DEFWORD    trk_porttrgper    ;portamento (cmd 3) target period
  3456.     DEFBYTE    trk_vibshift    ;vibrato shift for ASR instruction
  3457.     DEFBYTE    trk_vibrspd    ;vibrato speed/size (cmd 4 qualifier)
  3458.     DEFWORD    trk_vibrsz    ;vibrato size
  3459.     DEFLONG    trk_synthptr    ;pointer to synthetic/hybrid instrument
  3460.     DEFWORD    trk_arpgoffs    ;SYNTH: current arpeggio offset
  3461.     DEFWORD    trk_arpsoffs    ;SYNTH: arpeggio restart offset
  3462.     DEFBYTE    trk_volxcnt    ;SYNTH: volume execute counter
  3463.     DEFBYTE    trk_wfxcnt    ;SYNTH: waveform execute counter
  3464.     DEFWORD    trk_volcmd    ;SYNTH: volume command pointer
  3465.     DEFWORD    trk_wfcmd    ;SYNTH: waveform command pointer
  3466.     DEFBYTE    trk_volwait    ;SYNTH: counter for WAI (volume list)
  3467.     DEFBYTE    trk_wfwait    ;SYNTH: counter for WAI (waveform list)
  3468.     DEFWORD    trk_synthvibspd    ;SYNTH: vibrato speed
  3469.     DEFWORD    trk_wfchgspd    ;SYNTH: period change
  3470.     DEFWORD    trk_perchg    ;SYNTH: curr. period change from trk_prevper
  3471.     DEFLONG    trk_envptr    ;SYNTH: envelope waveform pointer
  3472.     DEFWORD    trk_synvibdep    ;SYNTH: vibrato depth
  3473.     DEFLONG    trk_synvibwf    ;SYNTH: vibrato waveform
  3474.     DEFWORD    trk_synviboffs    ;SYNTH: vibrato pointer
  3475.     DEFBYTE    trk_initvolxspd    ;SYNTH: volume execute speed
  3476.     DEFBYTE    trk_initwfxspd    ;SYNTH: waveform execute speed
  3477.     DEFBYTE    trk_volchgspd    ;SYNTH: volume change
  3478.     DEFBYTE    trk_prevnote2    ;SYNTH: previous note
  3479.     DEFBYTE    trk_synvol    ;SYNTH: current volume
  3480.     DEFBYTE    trk_synthtype    ;>0 = synth, -1 = hybrid, 0 = no synth
  3481.     DEFLONG    trk_periodtbl    ;pointer to period table
  3482.     DEFWORD    trk_prevportspd    ;portamento (cmd 3) speed
  3483.     DEFBYTE    trk_decay    ;decay
  3484.     DEFBYTE    trk_fadespd    ;decay speed
  3485.     DEFLONG    trk_envrestart    ;SYNTH: envelope waveform restart point
  3486.     DEFBYTE    trk_envcount    ;SYNTH: envelope counter
  3487.     DEFBYTE    trk_split    ;0 = this channel not splitted (OctaMED V2)
  3488.     DEFWORD    trk_newper    ;new period (for synth use)
  3489.     DEFBYTE    trk_vibroffs    ;vibrato table offset \ DON'T SEPARATE
  3490.     DEFBYTE    trk_tremoffs    ;tremolo table offset /
  3491.     DEFWORD    trk_tremsz    ;tremolo size
  3492.     DEFBYTE    trk_tremspd    ;tremolo speed
  3493.     DEFBYTE    trk_tempvol    ;temporary volume (for tremolo)
  3494.     DEFWORD    trk_vibradjust    ;vibrato +/- change from base period \ DON'T SEPARATE
  3495.     DEFWORD    trk_arpadjust    ;arpeggio +/- change from base period/
  3496.         END
  3497.